天天看點

設計模式--工廠與抽象工廠的差別

    好久沒有寫部落格了,忙碌的11月,12月,耽擱了好久,看的設計模式書,也快忘幹淨了

設計模式--工廠與抽象工廠的差別

,小白最近被人問了這樣一個問題“工廠設計模式與抽象工廠設計模式的差別”,小白之前看了些關于他們差別的介紹,不過回答的并不好,還是從網上搜下别人的解釋吧。

以下是工廠模式和抽象工廠的舉例說明:

1、工廠方法模式(Factory Method)

工廠方法模式分為三種:

11、普通工廠模式,就是建立一個工廠類,對實作了同一接口的一些類進行執行個體的建立。首先看下關系圖:

設計模式--工廠與抽象工廠的差別

舉例如下:(我們舉一個發送郵件和短信的例子)

首先,建立二者的共同接口:

[java]  view plain copy

  1. public interface Sender {  
  2.     public void Send();  
  3. }  

其次,建立實作類:

[java]  view plain copy

  1. public class MailSender implements Sender {  
  2.     @Override  
  3.     public void Send() {  
  4.         System.out.println("this is mailsender!");  
  5.     }  
  6. }  

[java]  view plain copy

  1. public class SmsSender implements Sender {  
  2.     @Override  
  3.     public void Send() {  
  4.         System.out.println("this is sms sender!");  
  5.     }  
  6. }  

最後,建工廠類:

[java]  view plain copy

  1. public class SendFactory {  
  2.     public Sender produce(String type) {  
  3.         if ("mail".equals(type)) {  
  4.             return new MailSender();  
  5.         } else if ("sms".equals(type)) {  
  6.             return new SmsSender();  
  7.         } else {  
  8.             System.out.println("請輸入正确的類型!");  
  9.             return null;  
  10.         }  
  11.     }  
  12. }  

我們來測試下:

  1. public class FactoryTest {  
  2.     public static void main(String[] args) {  
  3.         SendFactory factory = new SendFactory();  
  4.         Sender sender = factory.produce("sms");  
  5.         sender.Send();  
  6.     }  
  7. }  

輸出:this is sms sender!

22、多個工廠方法模式,是對普通工廠方法模式的改進,在普通工廠方法模式中,如果傳遞的字元串出錯,則不能正确建立對象,而多個工廠方法模式是提供多個工廠方法,分别建立對象。關系圖:

設計模式--工廠與抽象工廠的差別

将上面的代碼做下修改,改動下SendFactory類就行,如下:

[java]  view plain copy public   class  SendFactory {       public  Sender produceMail(){  

  1.         return new MailSender();  
  2.     }  
  3.     public Sender produceSms(){  
  4.         return new SmsSender();  
  5.     }  
  6. }  

測試類如下:

[java]  view plain copy

  1. public class FactoryTest {  
  2.     public static void main(String[] args) {  
  3.         SendFactory factory = new SendFactory();  
  4.         Sender sender = factory.produceMail();  
  5.         sender.Send();  
  6.     }  
  7. }  

輸出:this is mailsender!

33、靜态工廠方法模式,将上面的多個工廠方法模式裡的方法置為靜态的,不需要建立執行個體,直接調用即可。

[java]  view plain copy

  1. public class SendFactory {  
  2.     public static Sender produceMail(){  
  3.         return new MailSender();  
  4.     }  
  5.     public static Sender produceSms(){  
  6.         return new SmsSender();  
  7.     }  
  8. }  

[java]  view plain copy

  1. public class FactoryTest {  
  2.     public static void main(String[] args) {      
  3.         Sender sender = SendFactory.produceMail();  
  4.         sender.Send();  
  5.     }  
  6. }  

輸出:this is mailsender!

總體來說,工廠模式适合:凡是出現了大量的産品需要建立,并且具有共同的接口時,可以通過工廠方法模式進行建立。在以上的三種模式中,第一種如果傳入的字元串有誤,不能正确建立對象,第三種相對于第二種,不需要執行個體化工廠類,是以,大多數情況下,我們會選用第三種——靜态工廠方法模式。

2、抽象工廠模式(Abstract Factory)

工廠方法模式有一個問題就是,類的建立依賴工廠類,也就是說,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則,是以,從設計角度考慮,有一定的問題,如何解決?就用到抽象工廠模式,建立多個工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。因為抽象工廠不太好了解,我們先看看圖,然後就和代碼,就比較容易了解。

設計模式--工廠與抽象工廠的差別

請看例子:

[java]  view plain copy

  1. public interface Sender {  
  2.     public void Send();  
  3. }  

兩個實作類:

[java]  view plain copy

  1. public class MailSender implements Sender {  
  2.     @Override  
  3.     public void Send() {  
  4.         System.out.println("this is mailsender!");  
  5.     }  
  6. }  

[java]  view plain copy

  1. public class SmsSender implements Sender {  
  2.     @Override  
  3.     public void Send() {  
  4.         System.out.println("this is sms sender!");  
  5.     }  
  6. }  

兩個工廠類:

[java]  view plain copy

  1. public class SendMailFactory implements Provider {  
  2.     @Override  
  3.     public Sender produce(){  
  4.         return new MailSender();  
  5.     }  
  6. }  

[java]  view plain copy

  1. public class SendSmsFactory implements Provider{  
  2.     @Override  
  3.     public Sender produce() {  
  4.         return new SmsSender();  
  5.     }  
  6. }  

在提供一個接口:

[java]  view plain copy

  1. public interface Provider {  
  2.     public Sender produce();  
  3. }  

測試類:

[java]  view plain copy

  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         Provider provider = new SendMailFactory();  
  4.         Sender sender = provider.produce();  
  5.         sender.Send();  
  6.     }  
  7. }  

其實這個模式的好處就是,如果你現在想增加一個功能:發及時資訊,則隻需做一個實作類,實作Sender接口,同時做一個工廠類,實作Provider接口,就OK了,無需去改動現成的代碼。這樣做,拓展性較好!

了解了這兩種設計模式,下面就看下這兩種模式的差別:

設計模式之抽象工廠模式和工廠方法模式差別:工廠模式:定義一個用于建立對象的借口,讓子類決定執行個體化哪一個類。

抽象工廠模式:為建立一組相關或互相依賴的對象提供一個接口,而且無需指定他們的具體類。

前者是讓子類決定執行個體化某個具體的類,後者是無需指定具體的類。定義上差別很明顯,也許了解起來有點抽象,

舉個具體的栗子:

工廠建立一種産品,抽象工廠建立的是一組産品,是一個産品系列。

這裡要注意的是“系列”的意思,也就是說,抽象工廠建立出的一組産品是成套的。

當你發現,有一個接口可以有多種實作的時候,可以考慮使用工廠方法來建立執行個體。

當你發現,有一組接口可以有多種實作方案的時候,可以考慮使用抽象工廠建立執行個體組。

如果産品單一,最合适用工廠模式,但是如果有多個業務品種、業務分類時,通過抽象工廠模式産生需要的對象是一種非常好的解決方式。

再通俗深化了解下:工廠模式針對的是一個産品等級結構 ,抽象工廠模式針對的是面向多個産品等級結構的。

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

工廠方法模式 抽象工廠模式
針對的是一個産品等級結構 針對的是面向多個産品等級結構
一個抽象産品類 多個抽象産品類
可以派生出多個具體産品類 每個抽象産品類可以派生出多個具體産品類
一個抽象工廠類,可以派生出多個具體工廠類 一個抽象工廠類,可以派生出多個具體工廠類
每個具體工廠類隻能建立一個具體産品類的執行個體 每個具體工廠類可以建立多個具體産品類的執行個體

舉個例子說明下:

用種蔬菜的例子來說明事實,最初的時候,由于規模小,隻種植一種蔬菜,根菜類蔬菜,這個時候由于種植方式比較簡單,采用簡單工廠模式即可,主要目的是讓勞工輕松,下達工廠種植即可,但是随着種植廠的發展以及市場的需求,要增加一種蔬菜類型種植了,莖菜,由于莖菜與根菜種植方式不一緻,就需要兩個專門的種植工廠來進行管理,那麼久采用工廠模式來管理,一個工廠負責一種作物的種植,這個時候産品可以了解為仍然在一個層次。但是随着科技的發展,我們逐漸要種植轉基因與非轉基因食品了,在以前的蔬菜種類上又增加了一個層次,這個時候無法将其作為一個層次來解決,是以必須采用抽象工廠的方式來解決。我用UML圖表示三種結構:

設計模式--工廠與抽象工廠的差別
設計模式--工廠與抽象工廠的差別
設計模式--工廠與抽象工廠的差別

上面的UML圖很明顯的就看出來了,抽象工廠可以建立多個産品類對象,如在種菜工廠中,有種根菜,種莖菜。工廠模式與抽象工廠模式以及簡單工廠模式隻有在具體應用的時候,分析具體的産品層級,然後選擇相應的設計模式。

而在沒一個層次,種菜勞工所關心的對象也不一樣,在簡單工廠模式下,勞工要想到種植蘿蔔還是白菜,在工廠模式下,勞工想到是種植根菜還是莖菜,而在抽象工廠模式下,則關心種植基因菜還是非基因菜

抽象工廠模式是工廠方法模式的更新版本,他用來建立一組相關或者互相依賴的對象。他與工廠方法模式的差別就在于,工廠方法模式針對的是一個産品等級結構;而抽象工廠模式則是針對的多個産品等級結構。在程式設計中,通常一個産品結構,表現為一個接口或者抽象類,也就是說,工廠方法模式提供的所有産品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的産品則是衍生自不同的接口或抽象類。

在抽象工廠模式中,有一個産品族的概念:所謂的産品族,是指位于不同産品等級結構中功能相關聯的産品組成的家族。抽象工廠模式所提供的一系列産品就組成一個産品族;而工廠方法提供的一系列産品稱為一個等級結構。我們依然拿生産汽車的例子來說明他們之間的差別。

設計模式--工廠與抽象工廠的差別

在上面的類圖中,兩廂車和三廂車稱為兩個不同的等級結構;而2.0排量車和2.4排量車則稱為兩個不同的産品族。再具體一點,2.0排量兩廂車和2.4排量兩廂車屬于同一個等級結構,2.0排量三廂車和2.4排量三廂車屬于另一個等級結構;而2.0排量兩廂車和2.0排量三廂車屬于同一個産品族,2.4排量兩廂車和2.4排量三廂車屬于另一個産品族。

明白了等級結構和産品族的概念,就了解工廠方法模式和抽象工廠模式的差別了,如果工廠的産品全部屬于同一個等級結構,則屬于工廠方法模式;如果工廠的産品來自多個等級結構,則屬于抽象工廠模式。在本例中,如果一個工廠模式提供2.0排量兩廂車和2.4排量兩廂車,那麼他屬于工廠方法模式;如果一個工廠模式是提供2.4排量兩廂車和2.4排量三廂車兩個産品,那麼這個工廠模式就是抽象工廠模式,因為他提供的産品是分屬兩個不同的等級結構。當然,如果一個工廠提供全部四種車型的産品,因為産品分屬兩個等級結構,他當然也屬于抽象工廠模式了。

總結

無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬于工廠模式,在形式和特點上也是極為相似的,他們的最終目的都是為了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因為他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由于類中的産品構成了不同等級結構中的産品族,它就變成抽象工廠模式了;而對于抽象工廠模式,當減少一個方法使的提供的産品不再構成産品族之後,它就演變成了工廠方法模式。

是以,在使用工廠模式時,隻需要關心降低耦合度的目的是否達到了。

下面是一些小夥伴的了解,也許了解起來會好了解點,僅供參考哈

1.抽象工廠模式比工廠方法更抽象。。。

抽象工廠模式是把工廠方法再封裝了一層。

2.本來一個工廠裡可以造汽車,空調,冰箱。

現在工廠獨立了,一個工廠造汽車,另一個工廠造空調,再另外一個工廠造冰箱。

3.工廠一般造一種産品

抽象工廠造許多種産品

4.工廠是一種抽象,将建立對象的過程抽象;而抽象工廠更進一層,把工廠本身都抽象了。

5.工廠是下訂單的時候知道哪一家工廠。

而抽象工廠是下訂單的時候還不知道哪一家。

6.工廠建立一種産品,抽象工廠建立的是一組産品,是一個産品系列。

這裡要注意的是“系列”的意思,也就是說,抽象工廠建立出的一組産品是成套的。

當你發現,有一個接口可以有多種實作的時候,可以考慮使用工廠方法來建立執行個體。

當你返現,有一組接口可以有多種實作方案的時候,可以考慮使用抽象工廠建立執行個體組。(這個講的挺好的。)

繼續閱讀