??? 系統(tǒng)的演化應(yīng)當(dāng)依賴于組合,而不是繼承;這就提出了將類的實例化委托給一個對象的要求,因此創(chuàng)建型模式將變的越來越重要。
創(chuàng)建型模式屬于對象創(chuàng)建模型。所謂對象創(chuàng)建模型就是說將實例化的工作委托給另一個對象來做。與之相對應(yīng)的是類創(chuàng)建模型,這是一種通過繼承改變被實例化的類。
?????? 創(chuàng)建型模式有兩個重要的特點:
1)?客戶不知道創(chuàng)建的具體類是什么(除非看源代碼)
2)?隱藏了類的實例是如何被創(chuàng)建和放在一起的
一。抽象工廠模式
1.意圖:提供一個創(chuàng)建
一系列相關(guān)或相互依賴對象的接口,而無需指定它們的具體的類。
2.適用場景:
1)一個系統(tǒng)要獨立于它的產(chǎn)品的創(chuàng)建、組合和表示時
2)一個系統(tǒng)要由多個產(chǎn)品系列中的一個來配置時
3)當(dāng)你要強調(diào)一系列相關(guān)的產(chǎn)品對象的設(shè)計以便進行聯(lián)合使用時
4)當(dāng)你提供一個產(chǎn)品類庫,而只想顯示它們的接口而不是實現(xiàn)時
3.UML圖——結(jié)構(gòu)

4.效果:
1)分離了具體的類,通過抽象接口將客戶與具體的類分離
2)易于交換產(chǎn)品系列
3)有利于產(chǎn)品的一致性
4)難以支持新種類的產(chǎn)品,比如我們現(xiàn)在有一個ProductC產(chǎn)品,我們需要增加類AbstractProductC,增加AbstractFactory::
CreanteProductC方法,并且兩個產(chǎn)品系列的實際創(chuàng)建者ConCreateFactory1、ConCreateFactor2都要實現(xiàn)該方
法。
可以通過給方法加參數(shù)的方式來指明創(chuàng)建的是什么產(chǎn)品,這樣客戶代碼就無需改變,只要傳遞不同的參數(shù)。AbstractFactory類只需要提供一個CreateProduct(const string& name)方法即可。
5.代碼實現(xiàn),以《深入淺出設(shè)計模式(java C#)》的動物工廠為例:
using?System;
namespace?AnimalWorld
{
????//?抽象大陸工廠
????abstract?class?ContinentFactory
????{
????????abstract?public?Herbivore?CreateHerbivore();
????????abstract?public?Carnivore?CreateCarnivore();
????}
????//非洲大陸,有角馬,獅子
????class?AfricaFactory?:?ContinentFactory
????{
????????override?public?Herbivore?CreateHerbivore()
????????{
????????????return?new?Wildebeest();
????????}
????????override?public?Carnivore?CreateCarnivore()
????????{
????????????return?new?Lion();
????????}
????}
????//?美洲大陸,有狼,野牛
????class?AmericaFactory?:?ContinentFactory
????{
????????override?public?Herbivore?CreateHerbivore()
????????{
????????????return?new?Bison();
????????}
????????override?public?Carnivore?CreateCarnivore()
????????{
????????????return?new?Wolf();
????????}
????}
????//食草動物"
????abstract?class?Herbivore
????{
????}
????//肉食動物"
????abstract?class?Carnivore
????{
????????//獵食食草動物的方法
????????abstract?public?void?Eat(?Herbivore?h?);
????}
????//角馬
????class?Wildebeest?:?Herbivore
????{
????}
????//獅子"
????class?Lion?:?Carnivore
????{
????????//重載獵食食草動物的方法
????????override?public?void?Eat(?Herbivore?h?)
????????{
????????????Console.WriteLine(?this?+?"?eats?"?+?h?);
????????}
????}
????//野牛
????class?Bison?:?Herbivore
????{
????}
????//狼
????class?Wolf?:?Carnivore
????{
????????//重載獵食食草動物的方法
????????override?public?void?Eat(?Herbivore?h?)
????????{
????????????Console.WriteLine(?this?+?"?eats?"?+?h?);
????????}
????}
????//動物世界類
????class?AnimalWorld
????{
????????private?Herbivore?herbivore;
????????private?Carnivore?carnivore;
????????//?創(chuàng)建兩種動物分類
????????public?AnimalWorld(?ContinentFactory?factory?)
????????{
????????????carnivore?=?factory.CreateCarnivore();
????????????herbivore?=?factory.CreateHerbivore();
????????}
????????//運行食物鏈
????????public?void?RunFoodChain()
????????{
????????????//肉食動物獵食食草動物
????????????carnivore.Eat(?herbivore?);
????????}
????}
????///?<summary>
????///?抽象工廠模式客戶應(yīng)用測試
????///?</summary>
????class?GameApp
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//創(chuàng)造并運行非洲動物世界
????????????ContinentFactory?africa?=?new?AfricaFactory();
????????????AnimalWorld?world?=?new?AnimalWorld(?africa?);
????????????world.RunFoodChain();
????????????//創(chuàng)造并運行美洲動物世界
????????????ContinentFactory?america?=?new?AmericaFactory();
????????????world?=?new?AnimalWorld(?america?);
????????????world.RunFoodChain();
????????????Console.Read();
????????}
????}
}
二。Builder模式
1.意圖:將一個
復(fù)雜對象的構(gòu)建與它的表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示(或者說產(chǎn)品)
2.適用場景:
1)當(dāng)創(chuàng)建復(fù)雜對象的算法應(yīng)該獨立于改對象的組成部分以及它們的裝配方式時
2)當(dāng)構(gòu)造過程必須允許被構(gòu)造的對象有不同的表示時
3.UML圖——結(jié)構(gòu)




Director接受一個Builder子類對象,完成創(chuàng)建過程,并通知Builder對象返回以及構(gòu)造好的產(chǎn)品。
4.效果:
1)可以使你改變一個對象的內(nèi)部表示
2)構(gòu)造代碼和表示代碼分開
3)可以對構(gòu)造過程進行更精細的控制
5。實現(xiàn):以一個車輛建造過程為例(C#)
using?System;
namespace?CarShop
{
????using?System;
????using?System.Collections;
????//指揮者,Director
????class?Shop{
????????public?void?Construct(?VehicleBuilder?vehicleBuilder?){
????????????vehicleBuilder.BuildFrame();
????????????vehicleBuilder.BuildEngine();
????????????vehicleBuilder.BuildWheels();
????????????vehicleBuilder.BuildDoors();
????????}
????}
????/*?"Builder?建造者",Builder
????抽象建造者具有四種方法
????裝配框架
????裝配發(fā)動機
????裝配輪子
????裝配車門
????*/
????abstract?class?VehicleBuilder
????{
????????protected?Vehicle?vehicle;
????????//返回建造完成的車輛
????????public?Vehicle?Vehicle{
????????????get{?return?vehicle;?}
????????}
????????abstract?public?void?BuildFrame();
????????abstract?public?void?BuildEngine();
????????abstract?public?void?BuildWheels();
????????abstract?public?void?BuildDoors();
????}
????//具體建造者-摩托車車間
????class?MotorCycleBuilder?:?VehicleBuilder
????{
????????override?public?void?BuildFrame(){
????????????vehicle?=?new?Vehicle(?"摩托車"?);
????????????vehicle[?"frame"?]?=?"MotorCycle?Frame";
????????}
????????override?public?void?BuildEngine(){
????????????vehicle[?"engine"?]?=?"500?cc";
????????}
????????override?public?void?BuildWheels(){
????????????vehicle[?"wheels"?]?=?"2";
????????}
????????override?public?void?BuildDoors(){
????????????vehicle[?"doors"?]?=?"0";
????????}
????}
????//具體建造者-轎車車間
????class?CarBuilder?:?VehicleBuilder
????{
????????override?public?void?BuildFrame(){
????????????vehicle?=?new?Vehicle(?"轎車"?);
????????????vehicle[?"frame"?]?=?"Car?Frame";
????????}
????????override?public?void?BuildEngine(){
????????????vehicle[?"engine"?]?=?"2500?cc";
????????}
????????override?public?void?BuildWheels(){
????????????vehicle[?"wheels"?]?=?"4";
????????}
????????override?public?void?BuildDoors(){
????????????vehicle[?"doors"?]?=?"4";
????????}
????}
????//?具體建造者-單腳滑行車車間
????class?ScooterBuilder?:?VehicleBuilder
????{
????????override?public?void?BuildFrame(){
????????????vehicle?=?new?Vehicle(?"單腳滑行車"?);
????????????vehicle[?"frame"?]?=?"Scooter?Frame";
????????}
????????override?public?void?BuildEngine(){
????????????vehicle[?"engine"?]?=?"none";
????????}
????????override?public?void?BuildWheels(){
????????????vehicle[?"wheels"?]?=?"2";
????????}
????????override?public?void?BuildDoors(){
????????????vehicle[?"doors"?]?=?"0";
????????}
????}
????//車輛產(chǎn)品類
????class?Vehicle
????{
????????private?string?type;
????????private?Hashtable?parts?=?new?Hashtable();
????????//筑構(gòu)函數(shù),決定類型
????????public?Vehicle(?string?type?){
????????????this.type?=?type;
????????}
????????//索引
????????public?object?this[?string?key?]{
????????????get{?return?parts[?key?];?}
????????????set{?parts[?key?]?=?value;?}
????????}
????????//顯示方法
????????public?void?Show()
????????{
????????????Console.WriteLine(?"\n---------------------------");
????????????Console.WriteLine(?"車輛類類型:?"+?type?);
????????????Console.WriteLine(?"?框架?:?"?+?parts[?"frame"?]?);
????????????Console.WriteLine(?"?發(fā)動機?:?"+?parts[?"engine"]?);
????????????Console.WriteLine(?"?#輪子數(shù):?"+?parts[?"wheels"]?);
????????????Console.WriteLine(?"?#車門數(shù)?:?"+?parts[?"doors"?]?);
????????}
????}
????///?<summary>
????///?建造者模式應(yīng)用測試
????///?</summary>
?????class?CarShop
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//?創(chuàng)造車間及車輛建造者
????????????Shop?shop?=?new?Shop();
????????????VehicleBuilder?b1?=?new?ScooterBuilder();
????????????VehicleBuilder?b2?=?new?CarBuilder();
????????????VehicleBuilder?b3?=?new?MotorCycleBuilder();
????????????//?筑構(gòu)并顯示車輛
????????????shop.Construct(?b1?);
????????????b1.Vehicle.Show();
????????????shop.Construct(?b2?);
????????????b2.Vehicle.Show();
????????????shop.Construct(?b3?);
????????????b3.Vehicle.Show();
????????????Console.Read();
????????}
????}
}
三。Factory Method模式
1.意圖:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化具體的哪一個類。
2.適用場景:
1)當(dāng)一個類不知道它所必須創(chuàng)建的對象的類的時候,讓子類來決定
2)當(dāng)一個類希望由它的子類來決定它所創(chuàng)建的對象的時候
3。UML圖——結(jié)構(gòu):

4.效果:
1)為子類提供回調(diào)函數(shù)
2)連接平行的類層次
3)?創(chuàng)建函數(shù)可以接收參數(shù)來決定創(chuàng)建什么產(chǎn)品
4)Factory Method容易導(dǎo)致創(chuàng)建過多的Creator的子類以對應(yīng)不同的產(chǎn)品,這個方法可以通過模板技術(shù)來解決
6.實現(xiàn),手機工廠,產(chǎn)品可能是Nokia,也可能是Motorola
using?System;
using?System.Collections.Generic;
using?System.Text;
namespace?HandPhone
{
????//手機接口
????interface?Mobile
????{
?????????void?call();
????}
????//手機工廠接口
????interface?MobileFactory
????{
??????????Mobile?createMobile();
????}
????//Nokia
????class?Nokia:Mobile
????{
????????public?void?call()
????????{
????????????Console.WriteLine("This?is?a?{0}?phone",?this.GetType().Name);
????????}
????}
????//Motorola
????class?Motorola?:?Mobile
????{
????????public?void?call()
????????{
????????????Console.WriteLine("This?is?a?{0}?phone",?this.GetType().Name);
????????}
????}
????//Motorola工廠
????class?MotorolaFactory?:?MobileFactory
????{
?????????public?Mobile?createMobile()
????????{
????????????return?new?Motorola();
????????}
????}
????//Nokia工廠
????class?NokiaFactroy?:?MobileFactory
????{
????????public?Mobile?createMobile()
????????{
????????????return?new?Nokia();
????????}
????}
????public?class?Client
????{
????????static?void?Main(String?[]args)
????????{
????????????MobileFactory?factory=null;
????????????Mobile?mobile=null;
????????????factory=new?NokiaFactroy();
????????????mobile=factory.createMobile();
????????????mobile.call();
????????????factory=new?MotorolaFactory();
????????????mobile=factory.createMobile();
????????????mobile.call();
????????????
????????}
????}
}
四。Prototype模式
1.意圖:通過原型實例指定創(chuàng)建對象的種類,并通過拷貝這些原型來創(chuàng)建新的對象
2.適用場景:
1)要實例化的類是在運行時刻指定的,比如動態(tài)裝載
2)為了避免創(chuàng)建一個與產(chǎn)品層次平行的工廠類層次
3)當(dāng)一個類的實例只能有幾個不同的狀態(tài)組合中的一種時,建立相應(yīng)數(shù)目的原型并克隆它們可能比每次用合適的狀態(tài)手工化該類更方便一些。
3.UML圖——結(jié)構(gòu):

4.效果:
1)運行時動態(tài)增加或者刪除產(chǎn)品
2)減少子類的構(gòu)造數(shù)目
3)用類動態(tài)配置應(yīng)用
4)動態(tài)指定新的對象,通過改變結(jié)構(gòu)或者值
5)缺陷在于每一個Prototype的子類都需要實現(xiàn)clone操作
5。實現(xiàn),無論java還是C#都從語言層次內(nèi)置了對prototype模式的支持。具體不再詳述。
五。singleton模式
1。意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點
2.適用場景:
1)當(dāng)需要類只有一個實例,并且客戶只能通過一個全局點去訪問它
2)當(dāng)這個唯一實例應(yīng)該是通過子類化可擴展的,并且客戶應(yīng)該無需更改代碼就能使用擴展的實例
3.UML圖:略
4.效果:
1)對唯一實例的受控訪問
2)縮小命名空間
3)允許對操作和表示的細化
4)允許可變數(shù)目的實例
5實現(xiàn),關(guān)于singleton在java多線程環(huán)境下的實現(xiàn),請見討論《
當(dāng)Singleton遇到multi-threading》,C#對singleton多線程環(huán)境下的能夠正確實現(xiàn)Double-checked模式:
public?sealed?class?Singleton
{
????private?static?volatile?Singleton?instance;
????private?static?object?syncRoot?=?new?Object();
????private?Singleton()?{}
????public?static?Singleton?Instance
????{
????????get?
????????{
????????????if?(instance?==?null)?
????????????{
????????????????lock?(syncRoot)?
????????????????{
????????????????????if?(instance?==?null)?
????????????????????????instance?=?new?Singleton();
????????????????}
????????????}
????????????return?instance;
????????}
????}
}
本文僅作速查記憶用,摘記于《設(shè)計模式——可復(fù)用面向?qū)ο筌浖A(chǔ)》和《深入淺出設(shè)計模式(java C#)》兩書