工厂模式解决初始化经常造成耦合的问题,将你从复杂的依赖中脱困。
实例化对象时,会使用new,但这是针对实现编程,而不是接口。这样让代码绑着具体类,会导致代码更脆弱,缺乏弹性。
在技术上,new没有错,毕竟这是Java的基础部分。真正令人犯难的是“改变”。需要找出会变化的方面,把它们从不变的部分分离出来。
比萨店实例
假设你有一个比萨店,制作比萨的初始代码:
Pizza orderPizza() {
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
但是你需要更多比萨类型,增加比萨类型:
Pizza orderPizza(String type) {
Pizza pizza;
// 根据类型,实例化具体类
if(type.equals("cheese")) {
pizza = new CheesePizza();
} else if(type.equals("greek")) {
pizza = new GreekPizza();
} else if(type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
// 准备,比如加上佐料
pizza.prepare();
// 烘烤
pizza.bake();
// 切片
pizza.cut();
// 装盒
pizza.box();
return pizza;
}
但是压力来自于增加更多的比萨类型。比如你需要增加新的披萨,Clam Pizza(蛤蜊比萨)、Veggie Pizza(素食披萨)。或者最近Greek Pizza 卖得不好,你决定将它从菜单中去掉。这些都会使orderPizza()出问题,而且也无法让orderPizza()对修改关闭。
现在我们将创建对象移到orderPizza()之外,用另外一个类专门负责创建对象。我们称这个类为“工厂”,工厂处理创建对象的细节。
下面为比萨店实现一个简单比萨工厂:
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
// 代码没变动,仍然是根据类型实例化对象
if(type.equals("cheese")) {
pizza = new CheesePizza();
} else if(type.equals("greek")) {
pizza = new GreekPizza();
} else if(type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
return pizza;
}
}
这样做的好处是,将创建对象的行为都限定在一个类里,其他调用,如比萨店菜单、宅急送都直接复用这个类。当比萨类型需要修改时,只需修改这个类即可。
定义简单工厂
简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。由于经常被使用,而被误认为是设计模式。
当经营成功,有了加盟店之后,比萨店又该如何扩展代码呢,请看下篇《HeadFirst设计模式-工厂模式(2)-工厂方法》