Java設計模式—工廠方法模式&抽象工廠模式

工廠方法模式與抽象工廠模式都是設計模式中重要而且常見的模式。

      工廠方法模式:定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。


通用類圖如下:



        在工廠方法模式中,抽象產品類Product負責定義產品的共性,實現對事物最抽象的定義;Creator爲抽象創建

類,也就是抽象工廠,具體如何創建產品類是由具體的實現工廠ConcreteCreator完成的。


工廠方法模式的擴展方式有很多種,下邊是工廠方法模式一個比較實用的源代碼:


抽象產品類:

  1. public abstract class Product {      
  2.      //產品類的公共方法  
  3.      public void method1(){  
  4.              //業務邏輯處理  
  5.      }    
  6.      //抽象方法  
  7.      public abstract void method2();      
  8. }  


具體的產品類可以有多個,都繼承於抽象產品類。

  1. public class ConcreteProduct1 extends Product {  
  2.      public void method2() {  
  3.              //業務邏輯處理  
  4.      }  
  5. }  
  6. public class ConcreteProduct2 extends Product {  
  7.      public void method2() {  
  8.              //業務邏輯處理  
  9.      }  
  10. }  


抽象工廠類負責定義產品對象的產生:

  1. public abstract class Creator {      
  2.      /* 
  3.       * 創建一個產品對象,其輸入參數類型可以自行設置 
  4.       * 通常爲String、Enum、Class等,當然也可以爲空 
  5.       */          
  6.      public abstract <T extends Product> T createProduct(Class<T> c);  
  7. }  


具體如何產生一個產品的對象,是由具體的工廠類實現的:

  1. public class ConcreteCreator extends Creator {       
  2.      public <T extends Product> T createProduct(Class<T> c){  
  3.              Product product=null;  
  4.              try {  
  5.                     product = (Product)Class.forName(c.getName()).newInstance();  
  6.              } catch (Exception e) {  
  7.                     //異常處理  
  8.              }  
  9.              return (T)product;           
  10.      }  
  11. }  

場景類如下所示:
  1. public class Client {  
  2.      public static void main(String[] args) {  
  3.              Creator creator = new ConcreteCreator();  
  4.              Product product = creator.createProduct(ConcreteProduct1.class);  
  5.              /* 
  6.               * 繼續業務處理 
  7.               */  
  8.      }  
  9. }  

該通用代碼是一個比較實用、易擴展的框架。



工廠方法模式的優點:

(1)良好的封裝性,代碼結構清晰。一個對象創建是有條件約束的,如一個調用者需要一個具體的產品對象,只要

知道這個產品的類名(或約束字符串)就可以了,不用知道創建對象的艱辛過程,降低模塊間的耦合。

(2)工廠方法模式的擴展性非常優秀。在增加產品類的情況下,只要適當地修改具體的工廠類或擴展一個工廠類,

就可以完成“擁抱變化”。

(3)屏蔽產品類。這一特點非常重要,產品類的實現如何變化,調用者都不需要關心,它只需要關心產品的接口,

只要接口保持不變,系統中的上層模塊就不要發生變化。因爲產品類的實例化工作是由工廠類負責的,一個產品對象

具體由哪一個產品生成是由工廠類決定的。



使用場景:


       首先,工廠方法模式是new一個對象的替代品,所以在所有需要生成對象的地方都可以使用,但是需要慎重地考

慮是否要增加一個工廠類進行管理,增加代碼的複雜度。




工廠方法模式的擴展:


(1)簡單工廠模式

當一個模塊只需要一個工工廠類時,我們可以將抽象工廠類kill掉,然後將具體工廠類中製造產品的方法前面加static

關鍵字,則,工廠方法模式就變爲了簡單工廠模式。

         該模式是工廠方法模式的弱化,因爲簡單,所以稱爲簡單工廠模式(Simple Factory Pattern),也叫做靜態工

廠模式。在實際項目中,採用該方法的案例還是比較多的,其缺點是工廠類的擴展比較困難,不符合開閉原則,但它

仍然是一個非常實用的設計模式。


(2)多工廠模式


當遇到一個複雜的項目,初始化一個對象很費事的時候,我們可以使用多工廠模式,即一個工廠只生產特定的某種產

品,實現了單一職責。每一個產品類都對應了一個創建類,好處就是創建類的職責清晰,而且結構簡單,但是給可擴展性和可維護性帶來了一定的影響。爲什麼這麼說呢?如果要擴展一個產品類,就需要建立一個相應的工廠類,這樣就增加了擴展的難度。因爲工廠類和產品類的數量相同,維護時需要考慮兩個對象之間的關係。

       當然,在複雜的應用中一般採用多工廠的方法,然後再增加一個協調類,避免調用者與各個子工廠交流,協調類

的作用是封裝子工廠類,對高層模塊提供統一的訪問接口。




抽象工廠模式


抽象工廠模式是一種比較常用的模式。


其定義如下:

爲創建一組相關或相互依賴的對象提供一個接口,而且無須指定它們的具體類。


通用類圖如下:



          抽象工廠模式是工廠方法模式的升級版本,在有多個業務品種、業務分類時,通過抽象工廠模式產生需要的

對象是一種非常好的解決方式。我們來看看抽象工廠的通用源代碼,首先有兩個互相影響的產品線(也叫做產族),

例如製造汽車的左側門和右側門,這兩個應該是數量相等的——兩個對象之間的約束,每個型號的車門都是不

一樣的,這是產品等級結構約束的,我們先看看兩個產品族的類圖,如下所示:



注意類圖上的圈圈、框框相對應,兩個抽象的產品類可以有關係,例如共同繼承或實現一個抽象類或接口。


通用源代碼如下:

  1. //抽象產品類  
  2. public abstract class AbstractProductA {     
  3.      //每個產品共有的方法  
  4.      public void shareMethod(){  
  5.      }  
  6.      //每個產品相同方法,不同實現  
  7.      public abstract void doSomething();  
  8. }  


產品A1的實現類
  1. public class ProductA1 extends AbstractProductA {  
  2.      public void doSomething() {  
  3.              System.out.println("產品A1的實現方法");  
  4.      }  
  5. }  


  1. 產品A2的實現類  
  2. public class ProductA2 extends AbstractProductA {  
  3.      public void doSomething() {  
  4.              System.out.println("產品A2的實現方法");  
  5.      }  
  6. }  
產品B與此類似,不再贅述。


  1. 抽象工廠類  
  2. public abstract class AbstractCreator {  
  3.      //創建A產品家族  
  4.      public abstract AbstractProductA createProductA();   
  5.      //創建B產品家族  
  6.      public abstract AbstractProductB createProductB();  
  7. }  

注意:有N個產品族,在抽象工廠類中就應該有N個創建方法。


  1. 產品等級1的實現類  
  2. public class Creator1 extends AbstractCreator {      
  3.      //只生產產品等級爲1的A產品  
  4.      public Abstract ProductA createProductA() {   
  5.              return new ProductA1();  
  6.      }  
  7.      //只生產產品等級爲1的B產品  
  8.      public AbstractProductB createProductB() {  
  9.              return new ProductB1();  
  10.      }  
  11. }  

  1. 產品等級2的實現類  
  2. public class Creator2 extends AbstractCreator {      
  3.      //只生產產品等級爲2的A產品  
  4.      public AbstractProductA createProductA() {   
  5.              return new ProductA2();  
  6.      }  
  7.      //只生產產品等級爲2的B產品  
  8.      public AbstractProductB createProductB() {  
  9.              return new ProductB2();  
  10.      }  
  11. }  
注意:M個實現工廠類,在每個實現工廠中,實現不同產品族的生產任務。

場景類如下:

  1. public class Client {  
  2.      public static void main(String[] args) {  
  3.              //定義出兩個工廠  
  4.              Abstract Creator creator1 = new Creator1();  
  5.              Abstract Creator creator2 = new Creator2();  
  6.              //產生A1對象  
  7.              AbstractProductA a1 =  creator1.createProductA();  
  8.              //產生A2對象  
  9.              AbstractProductA a2 = creator2.createProductA();  
  10.              //產生B1對象  
  11.              AbstractProductB b1 = creator1.createProductB();  
  12.              //產生B2對象  
  13.              AbstractProductB b2 = creator2.createProductB();  
  14.              /* 
  15.               * 然後在這裏就可以爲所欲爲了... 
  16.               */  
  17.      }  
  18. }  


抽象工廠模式的優點:

● 封裝性。

         每個產品的實現類不是高層模塊要關心的,它要關心的是什麼?是接口,是抽象,它不關心對象是如何創建出

來,這由誰負責呢?工廠類,只要知道工廠類是誰,我就能創建出一個需要的對象,省時省力,優秀設計就應該如

此。


● 產品族內的約束爲非公開狀態。


缺點:
       抽象工廠模式的最大缺點就是產品族擴展非常困難,爲什麼這麼說呢?我們以通用代碼爲例,如果要增加一個產

品C,也就是說產品家族由原來的2個增加到3個,看看我們的程序有多大改動吧!抽象類AbstractCreator要增加一個

方法createProductC(),然後兩個實現類都要修改,想想看,這嚴重違反了開閉原則,而且我們一直說明抽象類和接

口是一個契約。改變契約,所有與契約有關係的代碼都要修改,那麼這段代碼叫什麼?叫“有毒代碼”,——只要與這

段代碼有關係,就可能產生侵害的危險!



兩種設計模式的區別:

        區別在於產品,如果產品單一,最合適用工廠模式,但是如果有多個業務品種、業務分類時,通過抽象工廠模式產生需要的對象是一種非常好的解決方式。再通俗深化理解下:工廠模式針對的是一個產品等級結構 ,抽象工廠模式針對的是面向多個產品等級結構的。


工廠方法模式與抽象工廠模式對比:

工廠方法模式

抽象工廠模式

針對的是一個產品等級結構針對的是面向多個產品等級結構
一個抽象產品類多個抽象產品類
可以派生出多個具體產品類每個抽象產品類可以派生出多個具體產品類
一個抽象工廠類,可以派生出多個具體工廠類一個抽象工廠類,可以派生出多個具體工廠類
每個具體工廠類只能創建一個具體產品類的實例每個具體工廠類可以創建多個具體產品類的實例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章