工廠模式

一、定義

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

  (工廠模式是咱們最經常使用的實例化對象模式了,是用工廠方法代替new操做的一種模式)html

二、模式分類

  工廠模式根據抽象程度的不一樣分爲三種:簡單工廠模式(也叫靜態工廠模式)、工廠方法模式、以及抽象工廠模式java

三、主要優勢

  • 可使代碼結構清晰,有效地封裝變化。在編程中,產品類的實例化有時候是比較複雜和多變的,經過工廠模式,將產品的實例化封裝起來,使得調用者根本無需關心產品的實例化過程,只需依賴工廠便可獲得本身想要的產品。
  • 對調用者屏蔽具體的產品類。若是使用工廠模式,調用者只關心產品的接口就能夠了,至於具體的實現,調用者根本無需關心。即便變動了具體的實現,對調用者來講沒有任何影響。
  • 下降耦合度。產品類的實例化一般來講是很複雜的,它須要依賴不少的類,而這些類對於調用者來講根本無需知道,若是使用了工廠方法,咱們須要作的僅僅是實例化好產品類,而後交給調用者使用。對調用者來講,產品所依賴的類都是透明的。  

四、適用場景

        不論是簡單工廠模式,工廠方法模式仍是抽象工廠模式,他們具備相似的特性,因此他們的適用場景也是相似的。編程

        首先,做爲一種建立類模式,在任何須要生成複雜對象的地方,均可以使用工廠方法模式。有一點須要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只須要經過new就能夠完成建立的對象,無需使用工廠模式。若是使用工廠模式,就須要引入一個工廠類,會增長系統的複雜度。架構

       其次,工廠模式是一種典型的解耦模式,迪米特法則在工廠模式中表現的尤其明顯。假如調用者本身組裝產品須要增長依賴關係時,能夠考慮使用工廠模式。將會大大下降對象之間的耦合度。學習

       再次,因爲工廠模式是依靠抽象架構的,它把實例化產品的任務交由實現類完成,擴展性比較好。也就是說,當須要系統有比較好的擴展性時,能夠考慮工廠模式,不一樣的產品用不一樣的實現工廠來組裝。ui

五、工廠方法模式

      工廠方法模式有四個要素:spa

  • 工廠接口。工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。在實際編程中,有時候也會使用一個抽象類來做爲與調用者交互的接口,其本質上是同樣的。
  • 工廠實現。在編程中,工廠實現決定如何實例化產品,是實現擴展的途徑,須要有多少種產品,就須要有多少個具體的工廠實現。
  • 產品接口。產品接口的主要目的是定義產品的規範,全部的產品實現都必須遵循產品接口定義的規範。產品接口是調用者最爲關心的,產品接口定義的優劣直接決定了調用者代碼的穩定性。一樣,產品接口也能夠用抽象類來代替,但要注意最好不要違反里氏替換原則。
  • 產品實現。實現產品接口的具體類,決定了產品在客戶端中的具體行爲。

  前文提到的簡單工廠模式跟工廠方法模式極爲類似,區別是:簡單工廠只有三個要素,他沒有工廠接口,而且獲得產品的方法通常是靜態的。由於沒有工廠接口,因此在工廠實現的擴展性方面稍弱,能夠算所工廠方法模式的簡化版,關於簡單工廠模式,在此一筆帶過。code

實現例子:htm

(java)

#場景是這樣的:汽車由發動機、輪、底盤組成,如今須要組裝一輛車交給調用者。假如不使用工廠模式,代碼以下:
class Engine {
    public void getStyle(){
        System.out.println("這是汽車的發動機");
    }
}
class Underpan {
    public void getStyle(){
        System.out.println("這是汽車的底盤");
    }
}
class Wheel {
    public void getStyle(){
        System.out.println("這是汽車的輪胎");
    }
}
public class Client {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Underpan underpan = new Underpan();
        Wheel wheel = new Wheel();
        ICar car = new Car(underpan, wheel, engine);
        car.show();
    }
}

  能夠看到,調用者爲了組裝汽車還須要另外實例化發動機、底盤和輪胎,而這些汽車的組件是與調用者無關的,嚴重違反了迪米特法則,耦合度過高。而且很是不利於擴展。另外,本例中發動機、底盤和輪胎仍是比較具體的,在實際應用中,可能這些產品的組件也都是抽象的,調用者根本不知道怎樣組裝產品。假如使用工廠方法的話,整個架構就顯得清晰了許多。

interface IFactory {
    public ICar createCar();
}
class Factory implements IFactory {
    public ICar createCar() {
        Engine engine = new Engine();
        Underpan underpan = new Underpan();
        Wheel wheel = new Wheel();
        ICar car = new Car(underpan, wheel, engine);
        return car;
    }
}
public class Client {
    public static void main(String[] args) {
        IFactory factory = new Factory();
        ICar car = factory.createCar();
        car.show();
    }
}

  使用工廠方法後,調用端的耦合度大大下降了。而且對於工廠來講,是能夠擴展的,之後若是想組裝其餘的汽車,只須要再增長一個工廠類的實現就能夠。不管是靈活性仍是穩定性都獲得了極大的提升。

 六、抽象工廠模式

【每個模式都是針對必定問題的解決方案,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式針對的是多個產品等級結構】

  當每一個抽象產品都有多於一個的具體子類的時候,工廠角色怎麼知道實例化哪個子類呢?好比每一個抽象產品角色都有兩個具體產品。抽象工廠模式提供兩個具體工廠角色,分別對應於這兩個具體產品角色,每個具體工廠角色只負責某一個產品角色的實例化。每個具體工廠類只負責建立抽象產品的某一個具體子類的實例。【多對一

產品族:

  是指位於不一樣產品等級結構中,功能相關聯的產品組成的家族。通常是位於不一樣的等級結構中的相同位置上。顯然,每個產品族中含有產品的數目,與產品等級結構的數目是相等的,造成一個二維的座標系,水平座標是產品等級結構,縱座標是產品族。例如蔬菜、水果就是產品等級結構;產地北方、南方就是產品族

 

 1 <?php
 2 #抽象工廠模式
 3 
 4 #產品等級結構(水果、蔬菜)
 5 #產品水果
 6 interface Fruit{}
 7 #產品蔬菜
 8 interface Vegetable{}
 9 
10 #產品族(北方、南方)
11 #一個產品族對應各個產品等級
12 #北方水果
13 class NorthFruit implements Fruit
14 {
15     //一列操做
16 }
17 #南方水果
18 class SouthFruit implements Fruit
19 {
20     //一列操做
21 }
22 #北方蔬菜
23 class NorthVegetable implements Vegetable
24 {
25     //一列操做
26 }
27 #南方蔬菜
28 class SouthVegetable implements Vegetable
29 {
30     //一列操做
31 }
32 
33 #抽象工廠接口
34 #有多少個產品等級結構,接口就有多少個聲明方法
35 interface Factory
36 {
37     public function createFruit();
38     public function createVegetable();
39 }
40 #實現抽象接口,有多少個產品族就有多少個工廠類
41 #北方工廠類
42 class NorthFactory implements Factory
43 {
44     public function createFruit()
45     {
46         return new NorthFruit();
47     }
48 
49     public function createVegetable()
50     {
51         return new NorthVegetable();
52     }
53 } 
54 #南方工廠類
55 class SouthFactory implements Factory
56 {
57     public function createFruit()
58     {
59         return new SouthFruit();
60     }
61 
62     public function createVegetable()
63     {
64         return new SouthVegetable();
65     }
66 } 
67 
68 #------------------------------#
69 #客戶端
70 #想要哪一個對象就找工廠
71 $northFactory=new NorthFactory();
72 $a=$northFactory->createFruit();    #獲取北方水果對象
73 
74 ?>

 

優勢:

  • 封裝性
  • 可以快速增長產品等級結構

缺點:

  • 抽象工廠模式的產品族擴展比較困難

 

(以上是本身的一些看法,如有不足或者錯誤的地方請各位指出)

 做者:那一葉隨風   http://www.cnblogs.com/phpstudy2015-6/

 原文地址: https://www.cnblogs.com/phpstudy2015-6/p/6732784.html

 聲明:本博客文章爲原創,只表明本人在工做學習中某一時間內總結的觀點或結論。轉載時請在文章頁面明顯位置給出原文連接

相關文章
相關標籤/搜索