java - 工厂内部的 If 语句过多

标签 java c++ refactoring factory

我目前正在开发一个包含许多不同设计模式的应用程序。它需要遵循良好的实践,基本上没有代码味道。

我正在使用工厂方法来打印出随机类型的对象,但我必须使用 3 个 if 语句,这似乎效率低下...如果我想打印出 10 个不同的对象会怎样?是否只需要添加更多 if 语句就没有其他方法可以解决这个问题。

** 工厂中这个特定方法的最终用途是返回一个球类型的随机对象 (1)。

RandomGenerator ranGen = new RandomGenerator();
int randomNumber = ranGen.createRandomNumber(1,3);
if(randomNumber == 1){
     //return smallBall
}
else if(randomNumber ==2){
    //return mediumBall
}
else if(randomNumber == 3){
    //return largeBall
}

最佳答案

另一种方法是应用 prototype pattern .

在下面的例子中,我们有一个名为 RandomBallFactory 的类 通过克隆已注册的原型(prototype)来创建随机(唯一)Ball 实例。

优点:

  • 我们可以添加新的 Ball 子类,而无需更改 RandomBallFactory 实现。
  • 我们可以创建相同类型但具有不同参数的对象。
  • 我们没有 if 语句。

Java 示例:

import java.util.*;

abstract class Ball implements Cloneable {
    abstract String getName();
    public Ball clone() {
        Ball ball;
        try {
            ball = (Ball)super.clone();
        } catch (CloneNotSupportedException e) {
            ball = null;
        }
        return ball;
    }
}

class SmallBall extends Ball {
    public String getName() { return "smallBall"; }
}

class MediumBall extends Ball {
    public String getName() { return "mediumBall"; }
}

class LargeBall extends Ball {
    public String getName() { return "largeBall"; }
}

class RandomBallFactory {
    private final List<Ball> prototypes;

    public RandomBallFactory() {
        prototypes = new ArrayList<Ball>();
    }

    public void registerBall(Ball ball) {
        prototypes.add(ball);
    }

    public Ball createBall() {
        Random randomGenerator = new Random();
        Integer randomNumber = randomGenerator.nextInt(prototypes.size());
        return prototypes.get(randomNumber).clone();
    }
}

public class TestBalls {
    public static void main(String[] args) {
        RandomBallFactory randomBallFactory = new RandomBallFactory();
        randomBallFactory.registerBall(new SmallBall());
        randomBallFactory.registerBall(new MediumBall());
        randomBallFactory.registerBall(new LargeBall());

        Ball ball = randomBallFactory.createBall();
        System.out.println(ball.getName());
    }
}

C++ 示例:

#include <iostream>
#include <vector>
#include <memory>
#include <cstdlib>
#include <ctime>

class Ball {
public:
    Ball() { std::cout << __func__ << std::endl; }
    Ball(Ball& other) { std::cout << __func__ << " copy from " << other.getName() << std::endl; }
    virtual ~Ball() { std::cout << __func__  << std::endl; }
    virtual std::string getName() = 0;
    virtual Ball* clone() = 0;
};

class SmallBall : public Ball {
public:
    std::string getName() { return "smallBall"; }
    Ball* clone() { return new SmallBall(*this); }
};

class MediumBall : public Ball {
public:
    std::string getName() { return "mediumBall"; }
    Ball* clone() { return new MediumBall(*this); }
};

class LargeBall : public Ball {
public:
    std::string getName() { return "largeBall"; }
    Ball* clone() { return new LargeBall(*this); }
};

class RandomBallFactory {
private:
    std::vector<std::shared_ptr<Ball> > prototypes;

public:
    void registerBall(std::shared_ptr<Ball> ball_ptr) {
        prototypes.push_back(ball_ptr);
    }

    std::shared_ptr<Ball> createBall() {
        int randomNumber = std::rand() % prototypes.size();
        return std::shared_ptr<Ball>(prototypes.at(randomNumber)->clone());
    }
};

int main(void) {
    std::srand(std::time(0));
    RandomBallFactory randomBallFactory;

    std::shared_ptr<Ball> sb_ptr(std::make_shared<SmallBall>());
    std::shared_ptr<Ball> mb_ptr(std::make_shared<MediumBall>());
    std::shared_ptr<Ball> lb_ptr(std::make_shared<LargeBall>());

    randomBallFactory.registerBall(sb_ptr);
    randomBallFactory.registerBall(mb_ptr);
    randomBallFactory.registerBall(lb_ptr);

    std::shared_ptr<Ball> ball_ptr(randomBallFactory.createBall());
    std::cout << "random Ball is: " << ball_ptr->getName() << std::endl;
}

关于java - 工厂内部的 If 语句过多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33399948/

相关文章:

Java:Stack.pop() + 不兼容的类型

java - android studio gradle更新后,使用Fuel库无法解析方法 'get(java.lang.String)'

java - 带 ehcache : nonstrict vs. 严格读写的集群 hibernate 缓存

c++ - 如何运行实时服务器win winsock?

c++ - SetClipboardData() 期间的堆损坏

c# - 如何在一个方法调用中创建文件及其父目录?

java - 如何选择过去一个月的第一个星期一之前的星期日

c++ - 如何将 Qt qml 移植到带有 C++ 后端的 Web 服务器

重构许多嵌套的 if 或链式的 if 语句

Java——重构两个几乎相同的方法