工廠方法模式
一、定義
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到子類
工廠方法模式的通用類圖如下
在工廠方法模式中,抽象產品類Product定義產品的共性,實現對事物最抽象的定義;Creator爲抽象創建類(抽象工廠)
具體如何創建產品類是有具體創建類ConcreteCreator完成的
-
代碼示例
-
抽象產品類
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); //業務處理 product.method1(); product.method2(); } }
-
二、工廠方法模式優點
-
良好的封裝性,代碼結構清晰
一個對象創建是有條件約束的,如一個調用者需要一個具體的產品對象,只要知道這個產品的類名就可以了,不需要知道這個對象具體的創建過程,降低模塊間的耦合
-
工廠方式模式的擴展性非常優秀
在增加產品類的情況下,只要適當的修改具體工廠類或擴展一個工廠類,就可以完成“擁抱變化”
-
屏蔽產品類
產品類的實現如何變化,調用者都不需要關心,它只需要關心產品的接口,只要接口保持不變,系統中的上層模塊(暫理解爲越接近應用層,如上面的Client,模塊層級越高)就不需要發生變化。因爲產品類的實例化工作是由工廠類負責的,一個產品對象具體由哪一個產品生成是由工廠類決定的;
-
農場方法模式是解耦框架
高層次模塊只需要知道產品的抽象類,其他的實現類都不用關心。
三、使用場景
-
工廠方法是new一個對象的替代品,所以在所有需要生成對象的地方都可以使用,但是需要謹慎的考慮是否要增加一個工廠類進行管理,增加代碼的複雜度(缺點)
-
需要靈活的、可擴展的框架時,可以考慮採用工廠方法的模式。
-
工廠方法模式可以用在異構項目中,用一個工廠類管理外圍系統,減少耦合
-
可以使用在測試驅動開發的框架下。
例如,測試一個類A,就需要把與類A有關係的類B實例化,可以用工廠方法模式把類B虛擬出來,避免類A與類B的耦合
四、工廠方法模式的擴展
-
縮小爲簡單工廠模式
一個模塊僅需要一個一個工廠類,沒有必要把它產生出來,使用靜態的方法就可以。即將抽象工廠方法去掉,直接用實現工廠類,同時將實現工廠類的創建對象方法修改爲static類型,它也叫 靜態工廠
-
升級爲多個工廠類
當項目比較複雜時,所有的產品類都放到一個工廠方法中進行初始化會使代碼結構不清晰,例如一個產品有5個具體實現,每個實現類的初始化方法都不相同,如果寫在一個工廠方法中,勢必會導致該方法巨大無比,例如
public <T extends Product> T createProduct(Class<T> class) { Product Product = null; if(class == Product1.class){ //創建Product1對象,並初始化 }else if(class == Product2.class){ //創建Product2對象,並初始化 }else if(class == Product3.class){ //創建Product3對象,並初始化 }else if(class == Product4.class){ //創建Product4對象,並初始化 }else{ //創建Product5對象,並初始化 } return (T) product; }
而我們要做到結構清晰,就要爲每個產品定義一個創造者(實際工廠類),然後由調用者去選擇與那個工廠方法關聯,如
puclic class Product1Factory extend AbstractProductFactory{ public Product createProduct() { Product product=new Product1(); //Product1對象並初始化 return product; } } ...
public class Client { public static void main(String[] args) { Product product1 =new Product1Factory().createProduct(); Product product2 =new Product2Factory().createProduct(); Product product3 =new Product3Factory().createProduct(); //業務處理 } }
每個產品類對應一個創建類,好處就是創建類的職責清晰,而且接口簡單,但是給可擴展性和可維護性帶來了影響,要擴展一個產品類,就需要建立一個相應的工廠類,增加了擴展的難度。
一般採用多工廠方法後,會增加一個協調類,避免調用者與各個子工廠交流,協調類的作用是封裝子工廠類,對高層模塊提供統一的訪問接口。