在講抽象工廠之前,要從模式開始講起
先來看看模式的起源:
多年以前,有一位名叫克里斯多佛·亞歷山大(英文名Christopher
Alexander)的建築師爲了研究優秀的設計有沒有共性這一問題,他對建築物、城鎮、街道等,以及人類爲自己所建造的各種生活空間進行了大量的觀察。他發現,在特定的建築物中,優秀的結構都有一些共同之處,雖然它們結構互不相同,但可能都具有很高的質量。
例如:兩個門廊雖然結構上不同,但都具有很高的質量。不同的建築可能是爲了解決不同的問題。一個門廊可能是走道和前門之間的過渡,而另一個門廊可能是爲了在天氣炎熱時提供陰涼。或許,兩個門廊在解決同一個問題(過渡)時,也可採用不同的方式。亞歷山大看到了這一點,他知道結構不能與要解決的問題分離,因此,在尋找和描述設計質量一致性的探求中,亞歷山大認識到,必須觀察爲了解決同樣問題而設計的不同結構。
亞歷山大發現,通過這樣的方式——觀察解決相似問題的不同結構,可以縮小關注範圍,從而看清優秀設計之前的相似之處。他將這種相似之處稱之爲模式。
他對模式的定義是“在某一環境下某個問題的一種解決方案”。每個模式都描述了一個在我們的環境中會不斷重複出現的問題,並敘述了這個問題解決方案的要素,通過這種方式,同一解決方案能夠被反覆應用無數次,而每一次使用的具體方式可以不同。
亞歷山大對模式的描述包括如下四項:
1、模式的名稱
2、模式的目的,也就是解決的問題
3、實現方法
4、爲了實現該模式我們必須考慮的限制和約束因素
在20世紀90年代,軟件界有好多人在想,軟件開發中是否存在以某種相同的方式解決不斷重複出現的問題,是否可以用模式的方法來設計軟件,經過他們不斷的總結,答案是肯定的。
以現實生活中“路”的生成爲例:“地上本沒有路,走的人多了便成了路”。同理,設計模式是經驗的總結與傳承。不論是建築設計模式,還是軟件設計模式,這些經驗都源於“人”,所以說人是一個經驗性動物。在我們每天的生活或工作環境中,如果存在一些會影響我們生活或者工作的現象或問題,我們就對這些現象或問題做出一個判斷或處理。這些經驗總結源於實踐,也服務於實踐。從“模式”到“設計模式”,再到“面向對象設計模式”,這是一個從廣泛到具體的過程。“設計模式”是一個廣泛的概念,它既可以指建築中的設計模式,也可以指軟件開發中的設計模式等。“面向對象設計模式”是可複用面向對象軟件的基礎。三者的基本描述如下:
1、每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的解決方案。
2、設計模式描述了軟件開發過程中某一類常見問題的一般性解決方案。
3、面向對象設計模式是對在特定場景下,解決一般設計問題中類與相互通信對象的描述。
目前最有影響力的書籍是:《設計模式:可複用面向對象軟件的基礎》,它共編錄了23種設計模式,分三大類別:創建型模式、結構型模式、行爲模式,其中有一種創建型模式是抽象工廠設計模式。
在學習抽象工廠設計模式之前,要先知道簡單工廠模式
衆所周知,從結構可以看出,簡單工廠模式中的工廠依賴於所有的子類產品,客戶只需知道父類產品和工廠即可。工廠是整個模式的核心,以不變應萬變。它雖然使對象的創建與使用進行了分離,但一次只能創建一個對象。它不能實現一次創建一系列相互依賴對象的需求,爲此我們需要學習抽象工廠設計模式。
打個比方:我想買一個移動硬盤,那麼我只要告訴你硬盤工廠生產一塊120G的移動硬盤就可以了!至於你工廠內如何生產,那不是我關心的問題(哪怕是你工廠能生產40G、80G、160G的,也與我沒有關係),我只要給你工廠一個條件(120G),工廠給我一塊120G的硬盤就可以了,其它的我不想知道,也不需要知道不是嗎?那麼,不難看出,做爲客戶,我們只要知道工廠和父類產品就可以了,還工廠則是提供了一個接口,告訴客戶工廠可以生產移動硬盤!可以看出這個工廠只能生產移動硬盤這種產品!
現在問題來了,移動硬盤壞了,我還要再一塊硬盤,同時我還想再買一個CPU,再買一個顯示器,那這時怎麼辦,我們要去每個工廠都告訴一下嗎?答案那是不可能的(因爲我也哪個工廠生產CPU,哪個工廠生產顯示器)。那我們爲什麼不去一個既有CPU賣,又有顯示器賣,還有移動硬盤賣的地方呢?
那麼這時候我們只有有需求就可以被滿足了。這裏我們就把這
種地方抽象爲電腦抽象工廠。電腦這個抽象工廠都是由什麼組成的呢(比如:顯示器、CPU、顯卡、主板、內存、硬盤等),那麼這裏的產品因爲沒有被真正的製作出來,這裏只是知道電腦由什麼組成,所以我們把這樣的產品稱之爲抽象產品。
結論:抽象工廠生產抽象產品!
現在,如果一個公司(聯想)成立了,這家公司想打造一個自己的電腦品牌,那麼這家公司就應該有可以生產所有電腦組成所需的產品對吧?(比如:顯示器、CPU、顯卡、主板、內存、硬盤等等,即使不是自己工廠生產的,那麼也要從新把這個產品打上自己的商標),好了,下面開始要生產自己的顯示器了。問題來了,電腦中的顯示器(也就是抽象工廠中的抽象產品)有沒有公有接口或者說是方法呢?一定是有的,比如顯示器都可以顯示吧,都有一個數據線與電腦提供的接口相連接吧等等。這也就要求聯想在生產自己的顯示器的時候要遵循顯示器(抽象產品)的規則。然後在這個基礎上,再增加自己顯示器的功能,以便對抗其它生產商。如果再有一家公司(戴爾)也與聯想的一致.
結論:實體工廠生產實體產品
結論:抽象產品提供實體產品的訪問接口
結論:實體產品實現自己的功能。
如果現在大家還不太明白,那也不要緊,我現在用僞代碼寫一下:
抽象工廠
public abstract class
電腦抽象工廠
{
//大家都學過用接口做爲返回值類型吧,衆所周知,接口可以做參數傳遞同時也可做爲返回值,這裏不再講解接口.
public
abstract 顯示器抽象產品接口 生產顯示器的方法();
public abstract CPU抽象產品接口
生產CPU抽象產品();
}
抽象產品
public interface 顯示器抽象產品接口
{
返回值類型 顯示器裏的方法1();
返回值類型
顯示器裏的方法2();
}
public interface CPU抽象產品接口
{
返回值類型
CPU裏的方法1();
返回值類型 CPU裏的方法2();
}
實體工廠
public class 聯想電腦工廠 : 電腦抽象工廠//是由電腦抽象工廠派生的
{
public override
顯示器抽象產品接口 生產顯示器的方法()//生產聯想顯示器實體產品
{
return new
聯想顯示器實體產品();
}
public override CPU抽象產品接口
生產CPU抽象產品()//生產聯想CPU實體產品
{
return new
聯想CPU實體產品();
}
}
public class 戴爾電腦工廠 :
電腦抽象工廠//是由電腦抽象工廠派生的
{
public override 顯示器抽象產品接口
生產顯示器的方法()//生產戴爾顯示器實體產品
{
return new
戴爾顯示器實體產品();
}
public override CPU抽象產品接口
生產CPU抽象產品()//生產戴爾CPU實體產品
{
return new
戴爾CPU實體產品();
}
}
實體產品
聯想
public class 聯想顯示器實體產品:顯示器抽象產品接口
{
public 返回值類型
顯示器裏的方法1()
{
//實現
}
public 返回值類型
顯示器裏的方法2()
{
//實現
}
}
public class
聯想CPU實體產品:CPU抽象產品接口
{
public 返回值類型
CPU裏的方法1()
{
//實現
}
public 返回值類型
CPU裏的方法2()
{
//實現
}
}
戴爾
public class
戴爾顯示器實體產品:顯示器抽象產品接口
{
public 返回值類型
顯示器裏的方法1()
{
//實現
}
public 返回值類型
顯示器裏的方法2()
{
//實現
}
}
public class
戴爾CPU實體產品:CPU抽象產品接口
{
public 返回值類型
CPU裏的方法1()
{
//實現
}
public 返回值類型
CPU裏的方法2()
{
//實現
}
}
如果大家對抽象工廠、抽象產品、實體工廠、實體產品已經能夠理解,那麼請向下看:
爲了在調用時方便,我們在抽象工廠里加一個創建實體工廠的方法
public abstract class
電腦抽象工廠
{
//創建實體工廠
public static 電腦抽象工廠 選擇實體工廠(string
typename)
{
電腦抽象工廠 抽象工廠實體 = null;
switch (typename)
{
case
"聯想":
抽象工廠實體 = new 聯想電腦工廠();
break;
case "戴爾":
抽象工廠實體 = new
戴爾電腦工廠();
break;
}
return 抽象工廠實體;
}
//大家都學過用接口做爲返回值類型吧,衆所周知,接口可以做參數傳遞同時也可做爲返回值,這裏不再講解接口.
public
abstract 顯示器抽象產品接口 生產顯示器的方法();
public abstract CPU抽象產品接口
生產CPU抽象產品();
}
這裏在調用的時候就可以這樣使用了
public static void Main()
{
//電腦抽象工廠
電腦實體=電腦抽象工廠.選擇實體工廠("戴爾");
電腦抽象工廠
電腦實體=電腦抽象工廠.選擇實體工廠("聯想");
電腦實體.生產顯示器的方法();
電腦實體.生產CPU抽象產品();
//這樣,只要傳入一個品牌,就可以得到這個品牌的電腦了
}
寫這個東東花掉了我一晚上的時間,哎,累~~~~~
對了,大家有時間的話幫我點一下Google的廣告吧,
我的個人網站,呵呵,謝謝大家!點完後記得
在這裏留名喲,我好回謝!
好了,就寫這些了,文章絕對原創,所以有點亂,思路還不是太好,有錯誤或描述不準的還請大家指正,謝謝!