### 一、模式定義
抽象工廠模式(Abstract Factory Pattern):提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又
稱為Kit模式,屬于對象創建型模式。
### 二、產品族和等級結構
為了更清晰地理解抽象工廠模式,需要先引入兩個概念:
**產品等級結構 :**產品等級結構即產品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電
視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
**產品族 :**在抽象工廠模式中,產品族是指由同一個工廠生產的,位于不同產品等級結構中的一組產品,如海爾電器工廠生產的海爾電視
機、海爾電冰箱,海爾電視機位于電視機產品等級結構中,海爾電冰箱位于電冰箱產品等級結構中。

從上邊的圖中我們可以更清晰的看到同族產品和同一等級結構的產品的聯系和區別。海爾電視機和長虹電視機都是電視機的子類,這樣的關
系叫做同一等級結構;海爾電視機和海爾電冰箱都是海爾公司生產的產品,所以他們都是同族產品。
我們還可以通過下邊的相圖可以更加清楚的看出來,橫軸表示等級結構,向橫軸做垂線,在同一條垂線上的是同一個等級結構,縱軸便是產
品組,向縱軸做垂線,同一條垂線上的是一個產品族。

如果看了上邊的兩種解釋你還是不能明白同族產品和同一等級結構的產品的話,那么可以看一下下面的這個非常暴力的例子。
你的爺爺和你的外公,你的爸爸和你舅舅,你和你的表弟都是同一等級結構,而你的爺爺和你的爸爸還有你是一個產品族,你的外公和你的
舅舅還有你的表弟是一個產品族,現在能明白什么是產品族什么是同一等級結構了吧。
### 三、模式動機
- 在工廠方法模式中具體工廠負責生產具體的產品,每一個具體工廠對應一種具體產品,工廠方法也具有唯一性,一般情況下,一個具體工
廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產品對象,而不是單一的產品對象。
- 當系統所提供的工廠所需生產的具體產品并不是一個簡單的對象,而是多個位于不同產品等級結構中屬于不同類型的具體產品時需要使用
抽象工廠模式。
- 抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式與工廠方法模式最大的區別在于,工廠方法模式
針對的是一個產品等級結構,而抽象工廠模式則需要面對多個產品等級結構,一個工廠等級結構可以負責多個不同產品等級結構中的產品對
象的創建
。當一個工廠等級結構可以創建出分屬于不同產品等級結構的一個產品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單、有效
率。
### 四、模式結構

從上圖看以看出抽象工廠模式和工廠方法模式類似都是由四部分組成。
- 抽象工廠(AbstractFactory)角色:擔任這個角色的是抽象工廠模式的核心,是與應用系統的商業邏輯無關的。通常使用Java接口或者
抽象Java類實現。所有的具體工廠必須實現這個Java接口或繼承這個抽象的Java類。
- 具體工廠(Factory)角色:這個角色直接在客戶端的調用下創建產品的實例,這個角色含有選擇合適的產品對象的邏輯,而這個邏輯是
與應用系統商業邏輯緊密相關的。
- 抽象產品(AbstractProduct)角色:擔任這個角色的類是抽象工廠模式所創建的對象的父類,或它們共同擁有的接口。通常使用Java接
口或者抽象Java類實現這一角色。
- 具體產品(Product)角色:抽象工廠模式所創建的任何產品對象都是一個具體的產品類的實例。這是客戶端最終需要的東西,其內部一
定充滿了應用系統的商業邏輯。通常使用具體Java類實現這個角色。
與工廠方法模式不同的是,抽象工廠模式中的具體工廠不再是只能創建一種產品,一個具體的工廠可以創建一個產品族的產品。
### 五、實例分析
我們接著前邊土豪的故事繼續講。話說這個土豪還有一個愛好,就是打獵。但是土豪打獵是有要求的(畢竟土豪嘛,要就就得高一點),他
如果坐Audi車去打獵,那么他就一定要使用AK47這把槍(這是去打獵嗎?【偷笑】);如果他坐Benz車去打獵那么他就一定要用M4A1這把槍
,如果按照我們前邊講的工廠方法模式來編程,那么應該是建立一個Car的抽象工廠類CarFactory,然后Benz車的工廠繼承自這個抽象的父類
并實現生產Benz車的方法,Audi車的工廠繼承自這個抽象的父類并實現生產Audi車的方法。并且還要有一個生產Gun的抽象工廠類,由它的具
體子類工廠來實現生產AK47和M4A1。
這樣做是非常麻煩的,我們已經知道了如果土豪做Audi的話那他一定是使用AK47,所以我們可以使用一個工廠來同時生產Audi車和AK47,注
意我說的前提是我們已經知道了土豪一定是Audi車和AK47一起使用的,如果不滿足這個條件的話是不能使用抽象工廠模式來解決這個問題的
。
具體的代碼如下:
~~~
package com.myfactory.abstractfactory;
/**
* 僅僅定義生產同一族產品的兩個不同等級結構的產品接口,具體的實現由子類工廠來實現
* @author xing
*
*/
public abstract class AbstractFactory {
public abstract Car getCar();
public abstract Gun getGun();
}
~~~
~~~
package com.myfactory.abstractfactory;
/**
* Audi車的工廠同時生產Audi車和配套的AK47
* @author xing
*
*/
public class AudiFactory extends AbstractFactory{
public Car getCar() {
return new Audi();
}
public Gun getGun() {
return new AK47();
}
}
~~~
汽車的類和前邊的例子是一樣的這里不再重復,最后會附上完整的代碼。
~~~
package com.myfactory.abstractfactory;
public abstract class Gun {
abstract void fire();
}
~~~
~~~
package com.myfactory.abstractfactory;
public class AK47 extends Gun{
public AK47(){
System.out.println("Create an AK47");
}
public void fire(){
System.out.println("AK47 start fire");
}
}
~~~
在Main函數中就可以通過一個工廠創建兩個對象。
~~~
package com.myfactory.abstractfactory;
public class Main {
public static void main(String[] args) throws Exception {
//奔馳車司機
AbstractFactory factory = new BenzFactory();
//今天想做奧迪車
Car car = factory.getCar();
//開車
car.drive();
//獲得開Benz時要用的槍
Gun gun = factory.getGun();
//開火
gun.fire();
}
}
~~~
### 六、模式優點
- 抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創建。由于這種隔離,更換一個具體工廠就變得相對容易。所有的具體
工廠都實現了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統的行為。另外,應用
抽象工廠模式可以實現高內聚低耦合的設計目的,因此抽象工廠模式得到了廣泛的應用。
當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象。這對一些需要根據當前環境來決
定其行為的軟件系統來說,是一種非常實用的設計模式。
- 增加新的具體工廠和產品族很方便,無須修改已有系統,符合“開閉原則”。
### 七、模式缺點
- 在添加新的產品對象時,難以擴展抽象工廠來生產新種類的產品,這是因為在抽象工廠角色中規定了所有可能被創建的產品集合,要支持
新種類的產品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。
- 開閉原則的傾斜性(增加新的工廠和產品族容易,增加新的產品等級結構麻煩)。
### 八、適用場景
1、一個系統不應當依賴于產品類實例如何被創建、組合和表達的細節,這對于所有形態的工廠模式都是重要的。
2、這個系統的產品有多于一個的產品族,而系統只消費其中某一族的產品。
3、同屬于同一個產品族的產品是在一起使用的,這一約束必須在系統的設計中體現出來。
4、系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴與實現。
### 九、抽象工廠模式的退化
當抽象工廠模式中每一個具體工廠類只創建一個產品對象,也就是只存在一個產品等級結構時,抽象工廠模式退化成工廠方法模式;當工廠
方法模式中抽象工廠與具體工廠合并,提供一個統一的工廠來創建產品對象,并將創建對象的工廠方法設計為靜態方法時,工廠方法模式退
化成簡單工廠模式。
源碼下載:[http://download.csdn.net/detail/xingjiarong/9296125](http://download.csdn.net/detail/xingjiarong/9296125)
- 前言
- 設計原則(一)"開-閉"原則(OCP)
- 設計原則(二)里氏替換原則(LSP)
- 設計原則(三)組合復用原則
- 設計原則(四)依賴倒置原則(DIP)
- 設計模式(一)簡單工廠模式
- 設計模式(二)工廠方法模式
- 設計模式(三)抽象工廠模式
- 設計模式(四)單例模式
- 設計模式(五)創建者模式(Builder)
- 設計模式(六)原型模式
- 設計模式(七)門面模式(Facade Pattern 外觀模式)
- 設計模式(八)橋梁模式(Bridge)
- 設計模式(九)裝飾模式(Decorator)
- 設計模式(十)適配器模式
- 設計模式(十一)策略模式
- 設計模式(十二)責任鏈模式
- 設計模式之UML(一)類圖以及類間關系(泛化 、實現、依賴、關聯、聚合、組合)
- 設計模式之橋梁模式和策略模式的區別