2011年11月19日 星期六

Design Pattern 比對(2) Factory Method和 Abstract Factory的異同

Factory Method Pattern(工廠方法模式),與Abstract Factory Pattern抽象工廠,其實都是在做同一件事,


就是要把建構子(constructor )封裝起來,使人不能隨意的去使用、修改。   這個與Singleton其實都是在做相同的事情,


因此,這三個也很常被使用在一起。  或是任兩個合併使用。


 


最簡單的區分方法:我先列個簡單的小表 (但我其實覺得這個分法很不好…有興趣的人真的去抓一下兩邊的UML圖去看一下比較好


 





































Factory Method Abstract Factory
以class來達成loose coupling的目的以object來達成loose coupling的目的
主要精神:inheritance(繼承)主要精神:composition(合成)
當利用Factory Method來建立物件時,需要繼承一個
class,並且override掉原本的Factory Method 
利用Abstract Factory的時候:重點是需要先定義一個
concrete Factory(具象化的工廠) 
目的:只是讓使用者不再需要每次修改原始的class可以將各種產品利用composition集合起來
 缺點:每一次要加入新產品:都必需要改變interface,甚至
需要將所有的工廠重新實作一次以適應新的interface 
建立一項商品:建立一整個商品家族
在java中Factory會看到的字:abstract在java中factory會看到的字:interface


我在想,大家之所以會常常把這兩個工廠搞混(書上說的,我以前也分不清楚),所以我就只寫在這裡…我想最主要的原因應該是:


工廠方法:裡面一定會看到abstract(抽象)這個字,而抽象工廠,卻是使用interface(介面) 這個key word,所以大家才容易搞混…


好吧…我必需要說…寫論文時也會發生類似的事…大家都喜歡一些特別的單字,使得那些單字都特別的搶手,先搶先贏,下好離手…自然就容易發生這種容易搞混的情形啦~


 




上面的是小抄:用來記錄兩種不同類型的factory所使用的最簡單的方法…


但如我所說:其實兩個pattern常常被合用,所以其實有時候很難去分辨究竟是哪個pattern


所以其實不是準備考試、或是教學一類,就不用分的太仔細了,重點是在於要理解他的精神以及目的。


 


重點都是在於要把constructor封裝起來,讓人不能隨意的去操作,


 


 


接下來我使用的是Head First Design Patterns 裡面的例子


Factory Method Pattern:


public abstract class PizzaStore{


   public Pizza orderPizza(String aType){


      Pizza pizza = createPizza(aType);


      pizza.prepare();


      pizza.bake();


      pizza.cut();


      pizza.box();


      return pizza;


   }


   public abstract Pizza createPizza();


}


這就是一個最簡單的Factory Method的例子:


重點在於createPizza這一個 method


此method必需要由subclass來定義,


接下來,看是什麼不同的pizza店,都可以靠createPizza來定義自己想要的pizza


比方說可以有:


public TaiwanPizzaStore extends PizzaStore{


  @override


  public Pizza createPizza(){


     //這邊可以加上各種台灣pizza的特殊作法


  }


}


這樣子一來,每當要新增不同的pizza製造方法時,只需要建立不同的PizzaStore工廠即可。


忽叫的方法都一樣…


 


比方說台灣的pizza工廠因為塑化劑而無法再食用,我們只需要換一個工廠


換成日本的pizza工廠,這樣子就不用擔心塑化劑了~~一樣可以製造~~(可是要怎麼送來台灣呢?這就是另外的故事了)


 


Abstract Factory則都是使用interface來使用:


 


public interface PizzaIngredientFactory{


    public Dough createDough();


    public Sauce createSauce();


    public Cheese createCheese();


    public Veggies[]  createVeggies();


...


}


 


接著就可以實作出不同的pizzaIngredientFactory了。


還是使用國家來分類的話~~不同國家的醬汁可以分


比方說四川的醬汁要辣一點,日本的醬汁要甜一點,美國的口味要比較重……


 


public class TWPizzaIngredientFacotry implements PizzaIngredientFactory


{


    public Dough createDough(){


       return new thickDough();  //為什麼台灣的pizza餅皮都要那麼厚呢?


    }


    public Sauce createSauce(){


         return new MarinaraSauce();//這邊就直接抄書上了


    }


    public Cheese createCheese(){  //台灣不產cheese,所以可以用各種cheese


        return new cheese();


    }


    .......


}


 


還可以靠定義不同的原料,來組合各種pizza(各種口味,各種國家)


 


 


Pizza的製作就很簡單了:


public class Pizza{


    PizzaIngredientFactory  mIngredientFactory;


   public Pizza(PizzaIngredientFactory  aIngredientFactory){


         mIngredientFactory  = aIngredientFactory;


   }


 


    ....


}


然後製作時就使用該factory得到物件…


 


 


-----


 


以上是簡單的例子,把大家容易搞混的地方舉出來


要真的搞懂這兩個在做什麼~請大家去翻書或是找線上教學~~這裡沒有


(除非讀者真的天才到我寫這樣子一小段你們就搞懂其工廠的精神了


 


 


----


其實最容易搞混的就這幾個吧~~Head First Design Patterns 我已經看完了,基本上沒有什麼會搞混了吧?


 


我會找時間再review一次,如果還有容易搞混的地方,我再來寫一篇3好了


2 則留言: