上一篇博文:http://blog.csdn.net/huruzun/article/details/26715369 已经很详细的讲述了工厂模式,这篇将讲述与工厂模式关系很密切的抽象工厂模式。
工厂模式中披萨店设计已经很棒了:具有弹性框架,而且遵循设计原则。
现在披萨店的关键就在如何控制加盟店原料流程? 如何确保加盟店原料的一致?
通过工厂模式,我们很快就能发现,现在我们需要建造原料工厂来确保加盟店原料的一致性。
package abstrctFactory;
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
每个不同地点的加盟店在每个地区建立工厂。每个不同地方需要做的就是创建继承PizzaIngredientFactory 的子类实现每一个创建方法。
创建纽约的原料工厂
package abstrctFactory;
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
public Veggies[] createVeggies() {
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
上述代码中原料家族中每一种原料我们实现是纽约版本。
准备好了原料工厂的高质量原料,现在可以开始重做披萨了。先从抽象的Pizza类开始。
package abstrctFactory;
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
abstract void prepare();
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
void setName(String name) {
this.name = name;
}
String getName() {
return name;
}
public String toString() {
StringBuffer result = new StringBuffer();
result.append("---- " + name + " ----\n");
if (dough != null) {
result.append(dough);
result.append("\n");
}
if (sauce != null) {
result.append(sauce);
result.append("\n");
}
if (cheese != null) {
result.append(cheese);
result.append("\n");
}
if (veggies != null) {
for (int i = 0; i < veggies.length; i++) {
result.append(veggies[i]);
if (i < veggies.length-1) {
result.append(", ");
}
}
result.append("\n");
}
if (clam != null) {
result.append(clam);
result.append("\n");
}
if (pepperoni != null) {
result.append(pepperoni);
result.append("\n");
}
return result.toString();
}
}
抽象Pizza类中,注意到prepare()方法是抽象的,这个方法中需要收集披萨所需要的原料,而这些原料当然来自原料工厂。
现在有了抽象披萨,可以开始创建各个地区风味的披萨了。
package abstrctFactory;
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
要制造原料每个披萨类型都要从构造器参数中得到一个工厂,prepare() 方法 通过这个工厂获得该种类披萨所需要的原料。
再回到披萨店,每个披萨店需要有一个原料工厂,看下面代码:
package abstrctFactory;
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("New York Style Cheese 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;
}
}
说了这么多了,给出抽象工厂模式定义吧。
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
下图是该模式的类图关系:
下图展示了这个示例的完整类图: