在設計模式中工廠模式此章的開頭, 便先點出問題所在, 為什麼我麼要使用工廠模式. 首先還記得設計原則 : Coding to interface, not implementation. 當每次我們使用 new 這個關鍵字, 其實就是在使用Concrete 的類別而非介面. 而這會牴觸到設計原則 : Open for extension, close for modification (OCP). 當有新的實體類別產生時, 則在你的代碼判斷改使用哪一個實體類別的區段, 便需要變更, 參考下面代碼 :
- Duck duck;
- if(picnic) {
- duck = new MallardDuck();
- } else if(hunting) {
- duck = new DecoyDuck();
- }
工廠模式定義與介紹 :
在這裡書上以Pizza 工廠作為介紹工廠模式的範例, 如同大部分人的直覺, 在Pizza 工廠使用 if/else 來依據不同需求實例化具體的Pizza 類別, 但隨著Pizza 的種類日益龐大, 這個 if/else 便變的相當繁瑣. 因此考慮到將 Pizza 具體實例化的代碼移出到另一個類別, 並由此類別統以產生客製化的Pizza 物件, 參考如下 :
透過上述的改造, 日後如果有新的Pizza 口味, 對方法 orderPizza 來說並不會受到影響, 它只需要對 SimplePizzaFactory 類別進行呼叫並獲得實現 IPizza 介面的物件, 並做接下來應該做的事而完成了對修改的封閉. 而上述介紹的正是 Simple Factory. 雖然它不是一個Design Pattern, 但是卻是用來介紹工廠模式的精隨很好用的範例.
接著事情變得更加複雜了, 由於PizzaStore 希望能夠透過經銷商來擴大它的服務範圍, 但是不同經銷商卻對Pizza 的口味有不同的堅持. 可能同樣是Cheese Pizza, 經銷商A要鹹一點, 但是經銷商B 卻想要辣一點. 由於不同經銷商造成同樣同樣Pizza 卻有不同的口味, 因此我們需要重新檢視目前的設計.
首先將PizzaStore 修改成抽象類別 AbstractPizzaStore, 再將此抽像類別提供各經銷商進行方法:createPizza 的客製化, 以提供不同地區獨特的Cheese Pizza, 參考如下代碼 :
* AbstractPizzaStore 代碼 :
- package hf.dp.ch04.store;
- import hf.dp.ch04.proto.IPizza;
- public abstract class AbstractPizzaStore {
- public IPizza orderPizza(String type) {
- IPizza pizza = null;
- pizza = createPizza(type);
- pizza.prepare();
- pizza.bake();
- pizza.cut();
- pizza.box();
- return pizza;
- }
- public abstract IPizza createPizza(String type); // 提供經銷商客製化Pizza 口味
- }
- package hf.dp.ch04.store;
- import hf.dp.ch04.proto.*;
- public class ChiagoStylePizzaStore extends AbstractPizzaStore{
- public IPizza createPizza(String type) {
- if(type.equals("cheese")) {
- return new ChiagoStyleCheesePizza();
- } else if(type.equals("clam")) {
- return new ChiagoStyleClamPizza();
- } else {
- return null;
- }
- }
- }
- package hf.dp.ch04.store;
- import hf.dp.ch04.proto.*;
- public class NYStylePizzaStore extends AbstractPizzaStore{
- @Override
- public IPizza createPizza(String type) {
- if(type.equals("cheese")) {
- return new NYStyleCheesePizza();
- } else if(type.equals("clam")) {
- return new NYStyleClamPizza();
- } else {
- return null;
- }
- }
- }
工廠方法模式 UML 圖 : 底下的Creator 就對應到 AbstractPizzaStore, 而 Product 介面就對應到 IPizza. 詳細代碼請參考附件.
範例代碼 :
* 呼叫工廠方法模式範例代碼 : 藉由不同的PizzaStore 來 order Pizza, 得到不同口味的Pizza.
package hf.dp.ch04;
- import hf.dp.ch04.store.*;
- import hf.dp.ch04.proto.*;
- public class Main {
- /*
- * 工廠方法模式呼叫範例代碼
- */
- public static void main(String[] args) {
- AbstractPizzaStore pizzaStore = new NYStylePizzaStore();
- AbstractPizzaStore pizzaStore2 = new ChiagoStylePizzaStore();
- IPizza cheesePizza = pizzaStore.orderPizza("cheese");
- System.out.println("John order "+cheesePizza.getName());
- cheesePizza = pizzaStore2.orderPizza("cheese");
- System.out.println("John order "+cheesePizza.getName());
- }
- }
執行結果 :
補充說明 :
* Caterpillar@Design Pattern: Simple Factory 模式
* Caterpillar@Design Pattern: Factory Method 模式
沒有留言:
張貼留言