C#面向對象設計模式縱橫談 第3講:Abstract Factory 抽象工廠模式

人文精神  >>>  技術的天空 溫和的思緒

2005.11.15 李建忠

new的問題

常規的對象創建方法:

image

new的問題:

-實現依賴,不能應對“具體實例化類型”的變化

解決思路:

-封裝變化點——哪里變化,封裝哪里

-潛臺詞:如果沒有變化,當然不需要額外的封裝!

 

工廠模式的緣起

變化點在“對象創建”,因此就封裝“對象創建”

面向接口編程——依賴接口,而非依賴實現

最簡單的解決方法:

image

 

創建一系列相互依賴的對象

假設一個游戲開發場景:

我們需要構造“道路”、“房屋”、“地道”、“叢林”……等等對象

image

image

 

簡單工廠的問題

簡單工廠的問題:

-不能應對“不同系列對象”的變化。比如有不同風格的游戲場景——對應不同風格的道路、房屋、地道……客戶程序相對穩定,但是靜態的簡單工廠卻可能成為變化點。

如何解決:

-使用面向對象的技術來“封裝”變化點

 

動機(Motivation)

在軟件系統中,經常面臨著“一系列相互依賴的對象”的創建工作;同時,由于需求的變化,往往存在更多系列對象的創建工作。

如何應對這種變化?如何繞過常規的對象創建方法(new),提供一種“封裝機制”來避免客戶程序和這種“多系列具體對象創建工作”的緊耦合?

 

意圖(Intent)

提供一個接口,讓該接口負責創建一系列“相關或者相互依賴的對象”,無需指定它們具體的類。

——《設計模式》GoF

 

結構(Structure)

image

A1和B1是一個系列,A2和B2是另一個系列。ConcreteFactory1是創建系列1的工廠方法,ConcreteFactory2是創建系列2的工廠方法。客戶程序Client只依賴了AbstractFactory和AbstractProductA、AbstractProductB,也就是客戶程序不依賴于具體實現,而是只依賴與抽象類。

如果現在需要創建一個系列3運用到客戶程序,我們只需要再寫一個系列3的工廠,繼承自AbstractFactory,這個工廠提供了2個實現:

CreateProductA();

CreateProductB();

它們分別返回ProductA3(繼承自AbstractProductA)、ProductB3(繼承自AbstractProductB)。

也就是說,如果新增了系列3,Client程序可以完全不用改動,可能只需要該一些配置文件,增加一些新dll就可以應對變化。

 

游戲框架中的AbstractFactory應用

image

image

這個例子里,Road就是AbstractProductA1,Building就是AbstractProductB1,FacilitiesFactory就是AbstractFactory。

 

客戶程序

image

可以看出,客戶程序依賴的全部是抽象類,在客戶程序代碼中沒有出現過任何具體的實現類。因為在系列需要變化的時候,是不需要改變抽象類的,只是增加一個抽象類的實現而已,又由于客戶程序只依賴于抽象,所以系列變化的時候客戶程序完全無需變化。

一個現代風格系列的實現

image

具體現代風格系列工廠實現

image

應用到具體程序(現代風格)

image

應用到具體程序(經典風格)

image

可以看出,風格由Modern改變為Classic的時候,我們封裝好的GameManager客戶程序沒有改變,這就是我們想要的結果。GameManager的邏輯非常復雜,現在它的穩定,能夠大大方便我們的工作。

 

AbstractFactory模式的幾個要點

1.如果沒有應對“多系列對象創建”的需求變化,則沒有必要使用AbstractFactory模式,這時候使用簡單的靜態工廠完全可以。

2."系列對象"指的是這些對象之間有相互依賴、或作用的關系,例如游戲開發場景中“道路”與“房屋”的依賴,“道路”與“地道”的依賴。

3.AbstractFactory模式主要在于應對“新系列”的需求變動。其缺點在于難以應對“新對象”的需求變動。

4.AbstractFactory模式經常喝FactoryMethod模式共同組合來應對“對象創建”的需求變化。

例如,如果是風格不是經常變化,而是其他內容變化(例如今天要添加道路的類、明天要添加沙漠的類),這樣用這種抽象工廠模式反而會把系統搞的很糟糕,因為抽象工廠類中的子類變化了,所有實現抽象工廠的類都需要去變化,重新實現,重新編譯和部署。

也就是說關鍵要看變化的方向和軸線在哪里。如果變化的軸線在多風格,那抽象工廠模式就很適用;如果變化的軸線在抽象工廠里面的對象,就最好不要使用這種模式。

 

.NET框架中的AbstractFactory應用

在ASP.Net編譯的時候,首先把aspx頁面文件先編譯成一個類,然后再把CodeBehind又編譯成一個類,CodeBehind的類繼承自Page類,而aspx頁面的類又繼承自CodeBehind類。在aspx頁面中處理的WebControl和HtmlControl實際上用到了AbstractFactory的運用,但是這個運用更多是體現在業務層次。

 

Builder模式和AbstractFactory模式的區別

Builder模式更強調的是對象部分的構建這樣一個嚴格的過程,它構建的是整個對象的各個部分。它把構建穩定下來之后,各個部分在變化,最后組合成一個整體的對象。

AbstractFactory模式構建的是一組系列交互的對象。

互相依賴、互相交互的對象和一個對象的各個部分是有區別的。

2010.9.22


MSDN 網絡廣播 李建忠 2013-08-22 08:42:15

[新一篇] C#面向對象設計模式縱橫談 第4講:Builder 生成器模式

[舊一篇] C#面向對象設計模式縱橫談 第2講:Singleton 單件
回頂部
寫評論


評論集


1 楼 2014/11/11 11:37:11 | 暫無
每張圖都不清楚
你他媽的是在貼個屁圖啊



稱謂:

内容:

驗證:


返回列表