十四、抽象工廠模式(Abstract Factory)

在前面兩章中,分別介紹了簡單工廠模式工廠方法模式,我們知道簡單工廠模式的優(yōu)點是去除了客戶端與具體產(chǎn)品的依賴,缺點是違反了“開放-關(guān)閉原則”;工廠方法模式克服了簡單工廠模式的缺點,將產(chǎn)品的創(chuàng)建工作放到具體的工廠類,每個工廠類負責(zé)生成一個產(chǎn)品。但是在實際應(yīng)用中,一個工廠類只創(chuàng)建單個產(chǎn)品的情況很少,一般一個工廠類會負責(zé)創(chuàng)建一系列相關(guān)的產(chǎn)品,如果我們要設(shè)計這樣的系統(tǒng),工廠方法模式顯然不能滿足應(yīng)用的需求,本章要介紹的抽象工廠模式,可以很好地解決一系列產(chǎn)品創(chuàng)建的問題。

1. 何為抽象工廠模式

定義: 提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類。

抽象工廠模式的結(jié)構(gòu)圖如圖1-1所示:

圖1-1 抽象工廠模式結(jié)構(gòu)圖

先對上面結(jié)構(gòu)圖的幾個角色進行說明:

(1)AbstractFactory:抽象工廠接口,里面應(yīng)該包含所有產(chǎn)品創(chuàng)建的抽象方法;
(2)ConcreteFactory1和ConcreteFactory2:具體的工廠,創(chuàng)建具有特定實現(xiàn)的產(chǎn)品對象;
(3)AbstractProductA和AbstractProductB:抽象產(chǎn)品,它們可能有多種不同的實現(xiàn)方式;
(4)ProductA1、ProductA2、ProductB1和ProductB2:具體的產(chǎn)品,是抽象產(chǎn)品的具體實現(xiàn)。

從結(jié)構(gòu)圖中可以看到,抽象工廠方法最大的好處是能夠很方便的變換產(chǎn)品系列(例如id<AbstractFactory> factory =[ [ConcreteFactory1 alloc] init],只需要將ConcreteFactory1換成ConcreteFactory2,就可以創(chuàng)建ProductA2和ProductB2)。另外,抽象工廠方法讓具體的創(chuàng)建實例過程與客戶端分離,客戶端是通過它們的抽象接口操作實例,產(chǎn)品的具體類名也被具體工廠的實現(xiàn)分離,不會出現(xiàn)在客戶代碼中(例如id<AbstractProductA> product = [factory createProductA],客戶端根本不知道具體的類名是ProductA1還是ProductA2)。
  但是,抽象工廠方法也是存在缺點的,比如說現(xiàn)在我們要增加一個新的產(chǎn)品,首先,我們需要增加三個類:AbstractProductC、ProductC1、ProductC2;另外,我們還需要更改三個類:AbstractFactory、ConcreteFactory1、ConcreteFactory2,這樣,很明顯是違背“開放-關(guān)閉原則”。這也是可以理解的,沒有任何一個設(shè)計模式是完美沒有瑕疵的,這就好比世界上沒有打不敗的武功一樣。我們可以做的就是在實際的需求中,盡可能的將變化點進行隔離,以達到變化發(fā)生的時候,對整個系統(tǒng)的影響最小,變化所帶來的變更和成本最低。

2. 代碼實現(xiàn)舉例

還是繼續(xù)簡單工廠模式工廠方法模式的應(yīng)用場景,這里將場景稍微改變一下:我們知道,繪制統(tǒng)計圖形的方案有多種,我們既可以使用OWC來繪制統(tǒng)計圖形,也可以使用HTML 5來繪制統(tǒng)計圖形,或者其他的一些第三方插件來進行繪圖,等等。這里我們用OWC和HTML 5繪制統(tǒng)計圖形來說明抽象工廠模式(注意:示例和場景只是為了說明設(shè)計模式的思想,并不是說實際開發(fā)中我們就會這么使用)。新應(yīng)用場景使用抽象工廠模式實現(xiàn)的結(jié)構(gòu)圖如圖2-1所示:

圖2-1 繪圖情景的抽象工廠模式結(jié)構(gòu)圖

更具結(jié)構(gòu)圖,一起來看看代碼實現(xiàn)方式:
(1)AbstractLine

@protocol AbstractLine <NSObject>

- (void)drawLine;

@end

(2)AbstractPie

@protocol AbstractPie <NSObject>

- (void)drawPie;

@end

(3)AbstractFactory

@protocol AbstractFactory <NSObject>

- (id<AbstractLine>)createLine;
- (id<AbstractPie>)createPie;

@end

(4)客戶端調(diào)用

id<AbstractFactory> factory = [[HTML5Factory alloc] init];
// id<AbstractFactory> factory = [[OWCFactory alloc] init];
id<AbstractLine> line = [factory createLine];
id<AbstractPie> pie = [factory createPie];

[line drawLine];
[pie drawPie];

3. 優(yōu)缺點及其使用場景

從調(diào)用代碼我們可以看到抽象工廠的兩個優(yōu)點:

能夠很方便的變換產(chǎn)品系列;
具體的創(chuàng)建實例過程與客戶端分離,客戶端是通過它們的抽象接口操作實例,產(chǎn)品的具體類名也被具體工廠的實現(xiàn)分離,不會出現(xiàn)在客戶代碼中。

抽象工廠模式的缺點我們前面也分析了:在新加產(chǎn)品的需求下,違背開放-封閉原則。通過優(yōu)缺點的比較,我們可以在如下場景下使用抽象工廠模式:功能模塊已經(jīng)非常成熟,基本上不需要太多修改,但是有可能會替換掉實現(xiàn)這些功能模塊的類的那種情況。比如說數(shù)據(jù)庫鏈接,所有的JDBC功能模塊幾乎一樣,只不過種類有所不同,有些是SQL-Server,有些是Oracle,那么這時候用抽象工廠來實現(xiàn),面對更換數(shù)據(jù)庫的情況,就比較方便了。

4. 幾種設(shè)計模式之間的對比

4.1 抽象工廠模式&建造者模式

抽象工廠模式和建造者模式都屬于創(chuàng)建型模式,它們在對象創(chuàng)建方面存在許多相似之處。但是,兩者也存在較大的區(qū)別,具體如下:

建造者模式 抽象工廠模式
構(gòu)建復(fù)雜對象 構(gòu)建簡單或復(fù)雜對象
以多個步驟構(gòu)建對象 以單一步驟構(gòu)建對象
以多種方式構(gòu)建對象 以單一方式構(gòu)建對象
在構(gòu)建過程的最后一步返回產(chǎn)品 立刻返回產(chǎn)品
專注一個特定產(chǎn)品 強調(diào)一套產(chǎn)品

4.2 抽象工廠模式&工廠方法模式

工廠方法模式是一種極端情況的抽象工廠模式,而抽象工廠模式可以看成是工廠方法模式的一種推廣。

工廠方法模式 抽象工廠模式
只有一個抽象產(chǎn)品類 有多個抽象產(chǎn)品類
工廠類一般只有一個方法,創(chuàng)建一種產(chǎn)品 工廠類一般有多個方法,創(chuàng)建一些列產(chǎn)品
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容