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

作者: 山天大畜  來源: 博客園  發布時間: 2010-11-08 15:23  閱讀: 1792 次  推薦: 0   原文鏈接   [收藏]  

  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模式構建的是一組系列交互的對象。互相依賴、互相交互的對象和一個對象的各個部分是有區別的。

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()