延續前一篇工廠方法模式,我們可以有多間加盟店,並且照著固定的 SOP 製作 pizza,加盟店只要專心處理 createPizza() 就好。最後還差一個步驟就能讓我們的 pizza 店更好,就是對 pizza 原料的控管。每個地區會有不同的原料,如何依照不同地區給予不同原料呢?要什麼原料就多一個工廠方法是個不錯的方法,既然會有很多原料工廠方法的話,把它們全集中在一起呢?這就是抽象工廠的概念了。我們可以先定一個抽象的原料工廠:
參考資料:
深入淺出設計模式(Head First Design Patterns)
public interface PizzaIngredientFactory { // 每個原料都是一個類別,每個原料都有一個 // 對應的方法建立該原料 public Sauce createSauce(); public Cheese createCheese(); public Vaggies createVaggies(); }假如每個工廠的實體(子類別)都有一種通用的機制要實作,例如都要先檢查原料,清洗原料之類的,上面的例子也可以改成抽象類別。
我們接下來就可以實作紐約風的原料工廠:
// 對於所有原料,紐約原料工廠都提供了紐約的版本 public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Sauce createSauce() { return new NYSauce(); } @Override public Cheese createCheese() { return new NYCheese(); } @Override public Veggies createVeggies() { return new NYVeggies(); } }接下來要修改 Pizza,讓它只使用工廠產生出來的產料:
public abstract class Pizza { String name; Sauce sauce; Veggies veggies; Cheese cheese; // 把這個方法宣告成抽象,以便讓次類別 // 使用不同工廠的原料 abstract public void prepare(); // 其他方法如 bake(), cut() 都不變, // 只有 prepare() 要改變 }
public class CheesePizza extends Pizza { PizzaIngredientFactory mFactory; // 次類別在建構時代入一個原料工廠 public CheesePizza(PizzaIngredientFactory factory) { mFactory = factory; } // 次類別一定要實作這個方法 @Override public void prepare() { // 這邊就是神奇的地方,工廠會因為建構式代入 // 不同的工廠,而產生不同的原料 // Pizza 不在乎是什麼工廠,只知道要原料 // 跟工廠拿就對了 sauce = mFactory.createSauce(); cheese = mFactory.createCheese(); veggies = mFactory.createVeggies(); } }最後修改一下 PizzaStore 就可以囉~
public class NYPizzaStore extneds PizzaStore { protected Pizza createPizza(String item) { Pizza pizza = null; // 因為是紐約店,所以使用紐約原料工廠 PizzaIngredientFactory factory = new NYPizzaIngredientFactory(); // 對於每一種 pizza,一律實體化一個新 pizza, // 並傳進該 pizza 所需的工廠, // 以取得對應的原料 if(item.equals("cheese")) { pizza = new CheesePizza(factory); pizza.setName("New York style cheese pizza"); } else if(item.equals("beef")) { pizza = new BeefPizza(factory); pizza.setName("New York style beef pizza"); } return pizza; } }上面的程式碼鬆綁了實際的產品,所以可以替換成不同的工廠,取得不同的行為,例如取的不是紐約風的 cheese ,而是其他地方的 cheese。
了解觀念後,就可以來定義抽象工廠模式了:
抽象工廠模式提供了一個介面,建立相關或相依物件之家族,而不需要明確指定具象類別
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
由類別圖可以看到,客戶的程式碼中只需涉及抽象工廠,執行其將自動使用實際的工廠。以上面的例子來看,NYPizzaStore 就是抽象工廠的客戶。
最後來比較一下抽象工廠以及工廠方法:
抽象工廠:主要是利用物件的合成,集結一些相關的產品,而在具象工廠使用工廠方法來實作要產出的產品。
工廠方法:通常是由繼承來的次類別來決定要產生哪種具象產品,其主要目的是將客戶從具象型態中鬆綁。
深入淺出設計模式(Head First Design Patterns)
留言
張貼留言