1.定義
Define an interface for creating an object,but let subclasses decide which class toinstantiate.Factory Method lets a class defer instantiation to subclasses.
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
2.詳解
在工廠方法模式中,抽象產品類Product負責定義產品的共性,實現對事物最抽象的定義;
Creator爲抽象創建類,也就是抽象工廠,具體如何創建產品類是由具體的實現工廠ConcreteCreator完成的。
3.實用代碼
抽象產品類:
public abstract class Product { //產品類的公共方法 public void method1(){ //業務邏輯處理 } //抽象方法 public abstract void method2(); }
具體產品類:
public class ConcreteProduct1 extends Product { public void method2() { //業務邏輯處理 } } public class ConcreteProduct2 extends Product { public void method2() { //業務邏輯處理 } }
抽象工廠類 :public abstract class Creator { /* * 創建一個產品對象,其輸入參數類型可以自行設置 * 通常爲String、Enum、Class等,當然也可以爲空 */ public abstract <T extends Product> T createProduct(Class<T> c); }
具體工廠類:
public class ConcreteCreator extends Creator { public <T extends Product> T createProduct(Class<T> c){ Product product=null; try { product = (Product)Class.forName(c.getName()).newInstance(); } catch (Exception e) { //異常處理 } return (T)product; } }
場景類 :public class Client { public static void main(String[] args) { Creator creator = new ConcreteCreator(); Product product = creator.createProduct(ConcreteProduct1.class); /* * 繼續業務處理 */ } }
4.工廠方法的優點
首先,良好的封裝性,代碼結構清晰。
一個對象創建是有條件約束的,如一個調用者需要一個具體的產品對象,只要知道這個產品的類名(或約束字符串)就可以了,不用知道創建對象的艱辛過程,降低模塊間的耦合。
其次,工廠方法模式的擴展性非常優秀。
在增加產品類的情況下,只要適當地修改具體的工廠類或擴展一個工廠類,就可以完成“擁抱變化”。例如在我們的例子中,需要增加一個棕色人種,則只需要增加一個BrownHuman類,工廠類不用任何修改就可完成系統擴展。
再次,屏蔽產品類。
這一特點非常重要,產品類的實現如何變化,調用者都不需要關心,它只需要關心產品的接口,只要接口保持不變,系統中的上層模塊就不要發生變化。因爲產品類的實例化工作是由工廠類負責的,一個產品對象具體由哪一個產品生成是由工廠類決定的。在數據庫開發中,大家應該能夠深刻體會到工廠方法模式的好處:如果使用JDBC連接數據庫,數據庫從MySQL切換到Oracle,需要改動的地方就是切換一下驅動名稱(前提
條件是SQL語句是標準語句),其他的都不需要修改,這是工廠方法模式靈活性的一個直接案例。最後,工廠方法模式是典型的解耦框架。
高層模塊值需要知道產品的抽象類,其他的實現類都不用關心,符合迪米特法則,我不需要的就不要去交流;也符合依賴倒置原則,只依賴產品類的抽象;當然也符合里氏替換原則,使用產品子類替換產品父類,沒問題!
工廠方法還可以變換成簡單工廠模式、多工廠模式,具體不再分析,詳情看《設計模式之禪》——秦小波
工廠方法模式在項目中使用得非常頻繁,以至於很多代碼中都包含工廠方法模式。該模式幾乎盡人皆知,但不是每個人都能用得好。熟能生巧,熟練掌握該模式,多思考工廠方法如何應用,而且工廠方法模式還可以與其他模式混合使用(例如模板方法模式、單例模式、原型模式等),變化出無窮的優秀設計,這也正是軟件設計和開發的樂趣所在。