Factory
New创建对象
当使用new创建对象时,是在实例化一个具体的类,如:
Duck duck = new MallardDuck();
当有一群相关的具体类时,通常会这样写:
Duck duck;if (picnic) {
duck = new MallardDuck();
} else if (hunting) {duck = new DecoyDuck();
} else if (inBathTub) {duck = new RubberDuck();
}这里有一些要实例化的具体类,究竟实例化哪个类,要在运行时根据条件决定,当看到这样的代码,一旦变化或扩展,就必须重新打开代码进行修改,这违背了“对扩展开放,对修改关闭”的原则。
认识变化的方面
假设有一家比萨店,作为店主人,你的代码可能这么写:
Pizza orderPizza() {Pizza pizza = new Pizza();
pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}但是你需要更多的比萨类型,所以必须增加一些代码:
Pizza orderPizza(String type) {Pizza pizza = new Pizza();
if (typr.equals("cheese")) {pizza = new CheesePizza();
} else if (typr.equals("greek")) {pizza = new GreekPizza();
} else if (typr.equals("pepperoni")) {pizza = new PepperoniPizza();
}pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}但是,当你发现竞争者已在他们的菜单中加入一些流行风味的比萨:ClamPizza(蛤蜊比萨)、VeggiePizza(素食比萨),也要把他们加入进去,而最近GreekPizza(希腊比萨)卖的不好,需要将其从菜单中去掉,于是需要修改上述代码。很明显,如果需要实例化具体类,将使orderPizza()出问题,无法让orderPizza()对修改关闭;但是,我们已经知道哪些会改变,哪些不会改变。最好将创建比萨的代码(上述代码中if…else…部分)移到另一个对象(SimplePizzaFactory)中,由这个新对象专职创建比萨。我们称这个新的对象为“工厂”,工厂(Factory)处理创建对象的细节。
建立一个简单比萨工厂
定义一个类,封装所有创建比萨对象。
public class SimplePizzaFactory {public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {pizza = new CheesePizza();
} else if ("pepperoni".equals(type)) {pizza = new PepperoniPizza();
} else if ("clam".equals(type)) {pizza = new ClamPizza();
} else if ("veggie".equals(type)) {pizza = new VeggiePizza();
}return pizza;
}}重做PizzaStore类:
public class PizzaStore {SimplePizzaFactory factory;public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}public Pizza orderPizza(String type) {
// 这里把new操作符替换成工厂对象的创建方法
Pizza pizza = factory.createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}}
定义简单工厂
简单工厂其实不是一个设计模式,而像是一种“编程习惯”。简单工厂用来为我们“暖身”,接下来是两个重量级的模式(工厂方法和抽象工厂),它们都是工厂。先来看看新的比萨店类图。