今天是設計模式的第二講,抽象工廠的設計模式,咱們仍是延續老辦法,一步一步的、演變的來說,先來看看一個對象建立的問題。編程
一、如何建立一個對象設計模式
常規的對象建立方法:框架
這樣的建立對象沒有任何問題,也能夠很好的使用。可是若是有需求的變化,好比,若是咱們換了一種道路呢,這時候就出現了問題。ui
new的問題:spa
-實現依賴,不能應對「具體實例化類型」的變化,Road是具體類型,全部使用到Road的地方都須要變化。若是常常變化,怎麼解決具體類型的變化呢?
設計
解決思路:3d
-封裝變化點——哪裏變化,封裝哪裏對象
-潛臺詞:若是沒有變化,固然不須要額外的封裝!blog
二、簡單工廠模式的由來
繼承
先說明一點,「簡單工廠模式」沒有寫在Gof的23種設計模式裏面,它是「工廠模式」的引子。
變化點在「對象建立」,所以就封裝「對象建立」
面向接口編程——依賴接口(此接口不是語言層面的Interface,此接口能夠是:Interface&抽象類),而非依賴實現
最簡單的解決方法:
這樣作,能夠隔離客戶程序和具體Road類型的變化,客戶程序依賴比較穩定的RoadFactory類型,這樣一來,客戶端的使用的接口就比較穩定了。
三、建立一系列相互依賴的對象
一個對象的問題解決了,那多個對象的建立問題怎麼解決呢?
假設一個遊戲開發場景:
咱們須要構造「道路」、「房屋」、「地道」、「叢林」……等等對象
很不錯,解決了一批對象的建立問題,這樣能夠保持客戶程序使用接口的穩定性。
四、多批對象的建立
簡單工廠的問題:
-不能應對「不一樣系列對象」的變化。好比有不一樣風格的遊戲場景——對應不一樣風格的道路、房屋、地道……客戶程序相對穩定,可是靜態的簡單工廠卻可能成爲變化點。
如何解決:
-使用面嚮對象的技術來「封裝」變化點,咱們就可使用「抽象工廠」設計模式
動機(Motivation)
在軟件系統中,常常面臨着「一系列相互依賴的對象」的建立工做;同時,因爲需求的變化,每每存在更多系列對象的建立工做。
如何應對這種變化?如何繞過常規的對象建立方法(new),提供一種「封裝機制」來避免客戶程序和這種「多系列具體對象建立工做」的緊耦合?
意圖(Intent)
提供一個接口,讓該接口負責建立一系列「相關或者相互依賴的對象」,無需指定它們具體的類。
結構(Structure)
ProductA1和ProductB1是一個系列,ProductA2和ProductB2是另外一個系列。ConcreteFactory1是建立系列1的工廠方法,ConcreteFactory2是建立系列2的工廠方法。客戶程序Client只依賴了AbstractFactory和AbstractProductA、AbstractProductB,也就是客戶程序不依賴於具體實現,而是隻依賴與抽象類。
若是如今須要建立一個系列3運用到客戶程序,咱們只須要再寫一個系列3的工廠,繼承自AbstractFactory,這個工廠提供了2個實現:
CreateProductA();
CreateProductB();
它們分別返回ProductA3(繼承自AbstractProductA)、ProductB3(繼承自AbstractProductB)。
也就是說,若是新增了系列3,Client程序能夠徹底不用改動,可能只須要該一些配置文件,增長一些新dll就能夠應對變化。
遊戲框架中的AbstractFactory應用
這個例子裏,Road就是AbstractProductA1,Building就是AbstractProductB1,FacilitiesFactory就是AbstractFactory。
客戶程序
能夠看出,客戶程序依賴的所有是抽象類,在客戶程序代碼中沒有出現過任何具體的實現類。由於在系列須要變化的時候,是不須要改變抽象類的,只是增長一個抽象類的實現而已,又因爲客戶程序只依賴於抽象,因此係列變化的時候客戶程序徹底無需變化。
一個現代風格系列的實現
具體現代風格系列工廠實現
應用到具體程序(現代風格)
應用到具體程序(經典風格)
能夠看出,風格由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模式構建的是一系列相互依賴、相互關聯的對象集合。