簡單工廠和工廠方法模式

zhifeng687發表於2016-01-11

簡單工廠和工廠方法模式

    簡單工廠:一個抽象產品類,派生出多個具體產品類;一個工廠類,每個工廠類可建立多個具體產品類的例項。“一對多”的關係。

    工廠方法:一抽象產品類派生出多個具體產品類;一抽象工廠類派生出多個具體工廠類;每個具體工廠類只能建立一個具體產品類的例項。

    即定義一個建立物件的介面(即抽象工廠類),讓其子類(具體工廠類)決定例項化哪一個類(具體產品類)。“一對一”的關係。


引用部落格連結:http://blog.csdn.net/carterjin/article/details/8055220


四、簡單工廠模式

簡單工廠模式,顧名思義就是模式比較簡單,實現起來比較具體的。

組成的三種角色分別為:

1、工廠類角色  :這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實現。例如你僱的司機,由他來處理你想開車的邏輯。
2、抽象產品角色:它一般是具體產品繼承的父類或者實現的介面。在java中由介面或者抽象類來實現。例如車這個模型,它是所有你想開的車的父類或介面。
3、具體產品角色:工廠類所建立的物件就是此角色的例項。在java中由一個具體類實現。例如具體的某輛車,賓士?寶馬?奧迪?

具體的類圖請看下面:


好,來簡單實現以下吧

來定義一個抽象產品角色:Car


[java] view plaincopy
  1. /** 
  2.  * 作為抽象產品類,即它只代表是某種產品,具體的細節由具體的產品來實現。 
  3.  * 
  4.  */  
  5. public interface Car {  
  6.       
  7.     /** 
  8.      * 子類需要實現的方法,具體如何開動 
  9.      */  
  10.     public abstract void drive();  
  11.   
  12. }  



Car類代表抽象的產品,是所有具體產品的父類。提供的開車方法,由具體的產品去實現。



再來定義具體產品角色:Benz、BMW、Audi

[html] view plaincopy
  1. /**  
  2.  * 賓士車,繼承與Car,實現了具體的開車細節  
  3.  */  
  4. public class Benz implements Car{  
  5.   
  6.     @Override  
  7.     public void drive() {  
  8.         // TODO Auto-generated method stub  
  9.         System.out.println("賓士車啟動,嗡~~~~");  
  10.     }  
  11.   
  12. }  
  13.   
  14. /**  
  15.  * 寶馬車,繼承與Car,實現了具體的開車細節  
  16.  */  
  17. public class BMW implements Car{  
  18.   
  19.     @Override  
  20.     public void drive() {  
  21.         // TODO Auto-generated method stub  
  22.         System.out.println("寶馬車啟動,嗡~~~~");  
  23.     }  
  24.   
  25. }  
  26.   
  27. /**  
  28.  * 奧迪車,繼承於Car,實現了具體的開車細節。  
  29.  */  
  30. public class Audi implements Car{  
  31.   
  32.     @Override  
  33.     public void drive() {  
  34.         // TODO Auto-generated method stub  
  35.         System.out.println("奧迪車啟動,嗡~~~~");  
  36.     }  
  37.   
  38. }  


這三個就是具體產品角色,是真正存在的車 。



下面,來最重要的工廠角色了,Driver。

[java] view plaincopy
  1. /** 
  2.  * 工廠類,由它來具體實現一些邏輯和業務上的細節 
  3.  * 
  4.  */  
  5. public class Driver {  
  6.       
  7.       
  8.     /** 
  9.      * 啟動一輛車,通過具體傳入的車名,來生成並返回該車。 
  10.      *  
  11.      * @param carName 需要開的車名。Benz,BMW,Audi 
  12.      * @return car 具體生成的車。注意多型。 
  13.      * @throws Exception 沒有找到傳入的車名時報出異常。 
  14.      */  
  15.     public static Car launch(String carName) throws Exception{  
  16.           
  17.         if"Benz".equals(carName)){  
  18.             return new Benz();  
  19.         }else if("BMW".equals(carName)){  
  20.             return new BMW();  
  21.         }else if("Audi".equals(carName)){  
  22.             return new Audi();  
  23.         }else{  
  24.             throw new Exception("沒有該車型:" + carName );  
  25.         }  
  26.     }  
  27.   
  28. }  

Driver類就是工廠類,它負責具體的業務邏輯。例如你想開什麼車,就傳入車名,由他來處理這個名字,併為你提供這輛車。如果沒有,則會告訴你一些錯誤。

該類有一個方法launch(),就是有它來處理業務細節的。具體怎麼實現,還要看具體的需求,這裡只是舉例。


最後,該我們上場了,Supremo!!

[java] view plaincopy
  1. public class Supremo {  
  2.     public static void main(String[] args){  
  3.           
  4.         try {  
  5.             Car car = Driver.launch("Benz");  
  6.             car.drive();  
  7.         } catch (Exception e) {  
  8.             // TODO Auto-generated catch block  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  
  12.   
  13. }  


看到了嗎?我們只是告訴司機我們想要開的車,司機就會自己進行處理並返回給我們,然後我們呼叫drive方法,就有具體的某輛車去執行開車方法了。


這便是簡單工廠模式了。怎麼樣,很簡單吧?那麼它帶來了什麼好處呢?
首先,使用了簡單工廠模式後,我們的程式不在“有病”,更加符合現實中的情況;
其次,客戶端免除了直接建立產品物件的責任,而僅僅負責“消費”產品(正如我們的行為)。


下面我們從開閉原則上來分析下簡單工廠模式。
當我們增加了一輛車的時候,只要符合抽象產品制定的原則,那麼只要通知工廠類知道就可以被客戶使用了。
那麼對於產品部分來說,它是符合開閉原則的——對擴充套件開放、對修改關閉;
缺點:
但是工廠部分好像不太理想,因為每增加一輛車,都要在工廠類中增加相應的商業邏輯和判斷邏輯,這顯自然是違背開閉原則的。
對於這樣的工廠類(在我們的例子中是為司機師傅),我們稱它為全能類或者上帝類。我們舉的例子是最簡單的情況,而在實際應用中,很可能產品是一個多層次的樹狀結構。由於簡單工廠模式中只有一個工廠類來對應這些產品,所以這可能會把我們的上帝類壞了,進而累壞了我們可愛的程式設計師:(


正如我前面提到的簡單工廠模式適用於業務將簡單的情況下。而對於複雜的業務環境可能不太適應阿。這就應該由工廠方法模式來出場了!!



五、工廠方法模式

上一種方法雖然很體現工廠設計模式,但過於簡單,所有的邏輯都在一個類裡實現,或多或少有點坑人的感覺啊,豈不是要累死人?萬惡的資本主義了???

我們人類太聰明瞭,發現問題了怎麼辦?馬上改進現有的機制唄。

在這種情況之下衍生了工廠方法模式,產品們還是依舊的產品們,但工廠?可不是曾經的那個工廠啦。“產房傳喜訊,人家生(升)啦”。

怎麼個意思?記得曾經的那個Driver類麼?現在,它已經變成了一個司機部門的主管,由具體的實現類,變成了一個父類(介面)。但只有一個光桿司令是不行滴,所以要招聘員工了,王師傅(賓士司機)、李師傅(寶馬司機)、張師傅(賓士司機)都來應聘成功!!!


來看看工廠方法模式的組成角色,比簡單工廠多了一個角色

1、抽象工廠類角色:工廠的抽象,是一般工廠的父類或實現的介面。在Java中由一個介面或抽象類來實現。例如我們程式的司機部門主管。
2、工廠類角色    :這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實現。例如你僱的司機,由他來處理你想開車的邏輯。
3、抽象產品角色  :它一般是具體產品繼承的父類或者實現的介面。在java中由介面或者抽象類來實現。例如車這個模型,它是所有你想開的車的父類或介面。
4、具體產品角色  :工廠類所建立的物件就是此角色的例項。在java中由一個具體類實現。例如具體的某輛車,賓士?寶馬?奧迪?


具體的類圖如下:



來看看實現吧~~~在簡單工廠的基礎之上,所有的產品都是不用動滴~~~需要改變的只是工廠類部門。

改動後的Driver

[java] view plaincopy
  1. /** 
  2.  * 工廠的介面,由它來定義一些需要完成的業務和邏輯,由具體的工廠去實現。例如司機部門主管。 
  3.  * 
  4.  */  
  5. public interface Driver {  
  6.     public abstract Car launchCar();  
  7. }  


怎麼樣?人家現在不管怎麼處理車了,人家只管發號施令,具體什麼車,你們不是有自己專門的司機麼?

來看看司機們吧~~~王師傅、李師傅、張師傅登場~~~


[java] view plaincopy
  1. /** 
  2.  * 賓士司機,繼承於Driver,是一個具體的工廠類。 
  3.  */  
  4. public class BenzDriver implements Driver{  
  5.   
  6.     @Override  
  7.     public Car launchCar() {  
  8.         // TODO Auto-generated method stub  
  9.           
  10.         return new Benz();  
  11.     }  
  12.   
  13. }  
  14.   
  15. /** 
  16.  * 寶馬司機,繼承於Driver,是一個具體的工廠類。 
  17.  */  
  18. public class BMWDriver implements Driver{  
  19.   
  20.     @Override  
  21.     public Car launchCar() {  
  22.         // TODO Auto-generated method stub  
  23.         return new BMW();  
  24.     }  
  25.   
  26. }  
  27.   
  28. /** 
  29.  * 奧迪司機,繼承於Driver,是一個具體的工廠類。 
  30.  */  
  31. public class AudiDriver implements Driver{  
  32.   
  33.     @Override  
  34.     public Car launchCar() {  
  35.         // TODO Auto-generated method stub  
  36.         return new Audi();  
  37.     }  
  38.   
  39. }  

三個司機都歸Driver類管,具體開什麼車,他們自己會去負責。


當然我們的行為也是需要改的,我們只要去告訴主管去開哪個車就好了

[java] view plaincopy
  1. public class Supremo {  
  2.     public static void main(String[] args){  
  3.           
  4.         // 告訴主管我們需要一個賓士車。  
  5.         Driver driver = new BenzDriver();  
  6.         Car car = driver.launchCar();  
  7.         car.drive();  
  8.           
  9.     }  
  10.   
  11. }  

我們今天心情高興,告訴主管我們想要開大奔粗們~~~主管就會很聽話的告訴賓士的師傅來準備好賓士車了。


工廠方法使用一個抽象工廠角色作為核心來代替在簡單工廠模式中使用具體類作為核心。
讓我們來看看工廠方法模式給我們帶來了什麼?使用開閉原則來分析下工廠方法模式。
當有新的產品(即我們的汽車)產生時,只要按照抽象產品角色、抽象工廠角色提供的原則來生成,那麼就可以被客戶使用,而不必去修改任何已有的程式碼。看來,工廠方法模式是完全符合開閉原則的!
使用工廠方法模式足以應付我們可能遇到的大部分業務需求。但是當產品種類非常多時,就會出現大量的與之對應的工廠類,這不應該是我們所希望的。所以我建議在這種情況下使用簡單工廠模式與工廠方法模式相結合的方式來減少工廠類:即對於產品樹上類似的種類(一般是樹的葉子中互為兄弟的)使用簡單工廠模式來實現。



 


相關文章