接上文。
重做披萨
现在已经有了一个抽象比萨,可以开始创建具体披萨子类了。子类间唯一的区别在于使用区域性的原料,至于比萨的做法都一样(面团+酱料+芝士),其他的比萨(蔬菜、蛤蜊等)也是如此。它们都依循着相同的准备步骤,只是使用不同的原料。
所以,我们不需要设计两个不同的类来处理不同风味的比萨,让原料工厂处理这个区域差异就可以了。下面是CheesePizza:
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
// prepare()方法一步一步地创建芝士比萨,每当需要原料时,就跟工厂要。
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
Pizza的代码利用相关的工厂生产原料。所生产的原料依赖所使用的工厂,Pizza类根本不关心这些原料,它只知道如何制作比萨。现在Pizza和区域原料之间被解耦。
再回到比萨店
我们几乎完工了,只需再到加盟店短暂巡视一个,确认他们使用了正确的比萨。也需要让他们能和本地的原料工厂搭上线,以纽约比萨店改造为例:
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
Pizza pizza = null;
// 纽约店会用到纽约比萨原料工厂
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if(item.equals("cheese")) {
// 把工厂传递给每一个比萨,以便比萨能从工厂中取得原料
pizza = new CheesePizza(ingredientFactory);
pizza.setName("NewYork Style Cheese Pizza");
} else if(item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
} else if(item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
} else if(item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
} else if(item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza");
}
return pizza;
}
}
小结
我们引入新类型的工厂,也就是抽象工厂,来创建比萨原料家族。通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码从实际工厂解耦,可以替换不同的工厂来取得不同的行为。
这其实是一种设计模式,抽象工厂模式
抽象工厂模式
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
抽象工厂模式和工厂方法模式非常相似,下篇具体解析两者的不同。