Abstract Factory
3. 抽象工廠模式(Abstract Factory)
3.1. 模式動機
- 在工廠方法模式中具體工廠負責生產具體的產品,每一個具體工廠對應一種具體產品,工廠方法也具有唯一性,一般情況下,一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產品對象,而不是單一的產品對象。
為了更清晰地理解工廠方法模式,需要先引入兩個概念: - 產品等級結構:產品等級結構即產品的繼承結構,如一個抽像類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
- 產品族:在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品,如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中。
- 當系統所提供的工廠所需生產的具體產品並不是一個簡單的對象,而是多個位於不同產品等級結構中屬於不同類型的具體產品時需要使用抽象工廠模式。
- 抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態。
- 抽象工廠模式與工廠方法模式最大的區別在於,工廠方法模式針對的是一個產品等級結構,而抽象工廠模式則需要面對多個產品等級結構,一個工廠等級結構可以負責多個不同產品等級結構中的產品對象的創建。當一個工廠等級結構可以創建出分屬於不同產品等級結構的一個產品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單、有效率。
3.2. 模式定義
抽象工廠模式(Abstract Factory Pattern):提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬於對象創建型模式。
3.3. 模式結構
抽象工廠模式包含如下角色:
- AbstractFactory:抽象工廠
- ConcreteFactory:具體工廠
- AbstractProduct:抽象產品
- Product:具體產品
3.4. 時序圖
3.5. 代碼分析
#include <iostream>
#include "AbstractFactory.h"
#include "AbstractProductA.h"
#include "AbstractProductB.h"
#include "ConcreteFactory1.h"
#include "ConcreteFactory2.h"
using namespace std ;
int main ( int argc , char * argv [])
{
AbstractFactory * fc = new ConcreteFactory1 (); AbstractProductA * pa = fc -> createProductA (); AbstractProductB * pb = fc -> createProductB (); pa -> use () ; pb -> eat (); AbstractFactory * fc2 = new ConcreteFactory2 ();
AbstractProductA * pa2 = fc2 -> createProductA ();
AbstractProductB * pb2 = fc2 -> createProductB (); pa2 -> use (); pb2 -> eat ();
////////////////////////////////////////////////// /////////
// ConcreteFactory1.cpp
// Implementation of the Class ConcreteFactory1
// Created on: 02-十月-2014 15:04:11
// Original author: colin
/////// ////////////////////////////////////////////////// //
#include "ConcreteFactory1.h"
#include "ProductA1.h"
#include "ProductB1.h"
AbstractProductA * ConcreteFactory1 :: createProductA (){
return new ProductA1 (); } AbstractProductB * ConcreteFactory1 :: createProductB (){ return new ProductB1 (); }
///////////////////////////////////////////////// /////////
// ProductA1.cpp
// Implementation of the Class ProductA1
// Created on: 02-十月-2014 15:04:17
// Original author: colin
/////// ////////////////////////////////////////////////// //
#include "ProductA1.h"
#include <iostream>
using namespace std ;
void ProductA1 :: use (){
cout << "use Product A1" << endl ; }
3.8. 優點
- 抽象工廠模式隔離了具體類的生成,使得客戶並不需要知道什麼被創建。由於這種隔離,更換一個具體工廠就變得相對容易。所有的具體工廠都實現了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統的行為。另外,應用抽象工廠模式可以實現高內聚低耦合的設計目的,因此抽象工廠模式得到了廣泛的應用。
- 當一個產品族中的多個對像被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象。這對一些需要根據當前環境來決定其行為的軟件系統來說,是一種非常實用的設計模式。
- 增加新的具體工廠和產品族很方便,無須修改已有系統,符合“開閉原則”。
3.9. 缺點
- 在添加新的產品對象時,難以擴展抽象工廠來生產新種類的產品,這是因為在抽象工廠角色中規定了所有可能被創建的產品集合,要支持新種類的產品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。
- 開閉原則的傾斜性(增加新的工廠和產品族容易,增加新的產品等級結構麻煩)。
3.10. 適用環境
在以下情況下可以使用抽象工廠模式:
- 一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節,這對於所有類型的工廠模式都是重要的。
- 系統中有多於一個的產品族,而每次只使用其中某一產品族。
- 屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。
- 系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。
3.11. 模式應用
在很多軟件系統中需要更換界面主題,要求界面中的按鈕、文本框、背景色等一起發生改變時,可以使用抽象工廠模式進行設計。
3.12. 模式擴展
“開閉原則”的傾斜性
-
- “開閉原則”要求系統對擴展開放,對修改封閉,通過擴展達到增強其功能的目的。對於涉及到多個產品族與多個產品等級結構的系統,其功能增強包括兩方面:
- 增加產品族:對於增加新的產品族,工廠方法模式很好的支持了“開閉原則”,對於新增加的產品族,只需要對應增加一個新的具體工廠即可,對已有代碼無須做任何修改。
- 增加新的產品等級結構:對於增加新的產品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產新產品的方法,不能很好地支持“開閉原則”。
- 抽象工廠模式的這種性質稱為“開閉原則”的傾斜性,抽象工廠模式以一種傾斜的方式支持增加新的產品,它為新產品族的增加提供方便,但不能為新的產品等級結構的增加提供這樣的方便。
工廠模式的退化
- 當抽象工廠模式中每一個具體工廠類只創建一個產品對象,也就是只存在一個產品等級結構時,抽象工廠模式退化成工廠方法模式;當工廠方法模式中抽象工廠與具體工廠合併,提供一個統一的工廠來創建產品對象,並將創建對象的工廠方法設計為靜態方法時,工廠方法模式退化成簡單工廠模式。
3.13. 總結
- 抽象工廠模式提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬於對象創建型模式。
- 抽象工廠模式包含四個角色:抽象工廠用於聲明生成抽象產品的方法;具體工廠實現了抽象工廠聲明的生成抽象產品的方法,生成一組具體產品,這些產品構成了一個產品族,每一個產品都位於某個產品等級結構中;抽象產品為每種產品聲明接口,在抽象產品中定義了產品的抽象業務方法;具體產品定義具體工廠生產的具體產品對象,實現抽象產品接口中定義的業務方法。
- 抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式與工廠方法模式最大的區別在於,工廠方法模式針對的是一個產品等級結構,而抽象工廠模式則需要面對多個產品等級結構。
- 抽象工廠模式的主要優點是隔離了具體類的生成,使得客戶並不需要知道什麼被創建,而且每次可以通過具體工廠類創建一個產品族中的多個對象,增加或者替換產品族比較方便,增加新的具體工廠和產品族很方便;主要缺點在於增加新的產品等級結構很複雜,需要修改抽象工廠和所有的具體工廠類,對“開閉原則”的支持呈現傾斜性。
- 抽象工廠模式適用情況包括:一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節;系統中有多於一個的產品族,而每次只使用其中某一產品族;屬於同一個產品族的產品將在一起使用;系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。
留言
張貼留言