抽象工廠的定義為:不需要指定具體的類,為建立一系列有關聯或有依賴關係的對象提供一個介面(Provide an interface for creating families of related or dependent objects without specifying their concrete classes)。
由定義可以看出,抽象工廠生產的是一系列產品(families of products),這就是與Factory 方法(Factory Method)的區別所在;還有一點就是生產出的產品具有相關性(related or dependent),因為同一類別的產品是在一個工廠中生產的,因而抽象工廠可以滿足這個約束(constraint),同時這點也是在使用抽象原廠模式時需要注意的事項 ---- 保持對象的一致性。
抽象工廠可以不抽象,這樣它可以同時被當作抽象工廠和具體工廠,子類工廠在繼承的時候可以選擇自己需要的產品去生產,不必生產每一種產品。
抽象共產生產的每一種產品可以使用原廠模式,如果產品的種類太多,為避免過多的繼承,則可以使用原型模式(Prototype)。
執行個體代碼如下(java)
1 首先定義一個工廠的介面,介面中定義了生產每一種產品的方法,用到了Factory 方法(Factory Method)。
public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createViggies(); public Pepperoni createPepperoni(); public Clams createClam();}
2 定義一個具體的工廠
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[] createVigges() { Veggies[] veggies = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() }; return veggies; } public Pepperoni createPepperoni() { return new SlicedPepperoni(); } public Clams createClam() { return new FreshClams(); }}
3 定義產品的基類
public abstract class Pizza { String name; String dough; String 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 setName(String name) { this.name = name; } String getName() { return name; } public String toString() { // code to print pizza here }}
3 具體的產品類
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(); }}
public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); clam = ingredientFactory.createClam(); }}
3 使用工廠類
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; }}
由於常常只用到一個工廠類的執行個體,因此可以把子類工廠類定義為singleton,這樣也可以使用到lazy initialization。