设计模式学习之四(上)—开自己的比萨店

前面说过其中之一的设计原则我们不应该依赖实现编程,但是当我们每次用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; 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; }

但压力来自于增加更多的比萨,或者某种比萨卖的不好我想从比萨店去掉,就要一再修改刚增加上的代码,但是比萨的准备,烘烤,包装多年来很少变,变的只是被制作的对象而已。既然已经看出来那些变化,那些不变化的地方,是我们封装变化的时候了,将创建对象移到orderPizzas()之外,移到别的地方,这个地方我们称之为工厂,但需要比萨时就向工厂要,至于比萨产生的细节我不关心,我只关心我是否能拿到比萨。我们建立一个简单比萨工厂:

public class SimplePizzaFactory { public Pizza orderPizza(String type){ Pizza pizza = null; if(type.equals("cheese")) { pizza = new CheesePizza(); } else if(type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if(type.equals("clam")) { pizza = new ClamPizza(); } else if(type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; } }

是时候修改我们的客户代码了,我们所要做的是向工厂要比萨,其他不用关心:

public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type){ Pizza pizza; //这里我们把new替换成了工厂创建方法 pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }

上面的简单工厂其实不是一个设计模式,反而更像一种编程习惯。有些编程人员习惯把它误认为是“工厂模式”。但也不要因为简单工厂不是一个真正的模式,就忽略他的用法,让我们看看新的比萨店的类图:

设计模式学习之四(上)—开自己的比萨店

谢谢简单工厂为我们暖身。接下来登场的是两个重量级模式,他们都是工厂,你将会看到更多的比萨。