Posted on 2007-03-17 17:01
dennis 閱讀(972)
評論(1) 編輯 收藏 所屬分類:
模式與架構 、
java 、
C#歷程
??? 系統的演化應當依賴于組合,而不是繼承;這就提出了將類的實例化委托給一個對象的要求,因此創建型模式將變的越來越重要。
創建型模式屬于對象創建模型。所謂對象創建模型就是說將實例化的工作委托給另一個對象來做。與之相對應的是類創建模型,這是一種通過繼承改變被實例化的類。
?????? 創建型模式有兩個重要的特點:
1)?客戶不知道創建的具體類是什么(除非看源代碼)
2)?隱藏了類的實例是如何被創建和放在一起的
一。抽象工廠模式
1.意圖:提供一個創建
一系列相關或相互依賴對象的接口,而無需指定它們的具體的類。
2.適用場景:
1)一個系統要獨立于它的產品的創建、組合和表示時
2)一個系統要由多個產品系列中的一個來配置時
3)當你要強調一系列相關的產品對象的設計以便進行聯合使用時
4)當你提供一個產品類庫,而只想顯示它們的接口而不是實現時
3.UML圖——結構

4.效果:
1)分離了具體的類,通過抽象接口將客戶與具體的類分離
2)易于交換產品系列
3)有利于產品的一致性
4)難以支持新種類的產品,比如我們現在有一個ProductC產品,我們需要增加類AbstractProductC,增加AbstractFactory::
CreanteProductC方法,并且兩個產品系列的實際創建者ConCreateFactory1、ConCreateFactor2都要實現該方
法。
可以通過給方法加參數的方式來指明創建的是什么產品,這樣客戶代碼就無需改變,只要傳遞不同的參數。AbstractFactory類只需要提供一個CreateProduct(const string& name)方法即可。
5.代碼實現,以《深入淺出設計模式(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;
????????//?創建兩種動物分類
????????public?AnimalWorld(?ContinentFactory?factory?)
????????{
????????????carnivore?=?factory.CreateCarnivore();
????????????herbivore?=?factory.CreateHerbivore();
????????}
????????//運行食物鏈
????????public?void?RunFoodChain()
????????{
????????????//肉食動物獵食食草動物
????????????carnivore.Eat(?herbivore?);
????????}
????}
????///?<summary>
????///?抽象工廠模式客戶應用測試
????///?</summary>
????class?GameApp
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//創造并運行非洲動物世界
????????????ContinentFactory?africa?=?new?AfricaFactory();
????????????AnimalWorld?world?=?new?AnimalWorld(?africa?);
????????????world.RunFoodChain();
????????????//創造并運行美洲動物世界
????????????ContinentFactory?america?=?new?AmericaFactory();
????????????world?=?new?AnimalWorld(?america?);
????????????world.RunFoodChain();
????????????Console.Read();
????????}
????}
}
二。Builder模式
1.意圖:將一個
復雜對象的構建與它的表示相分離,使得同樣的構建過程可以創建不同的表示(或者說產品)
2.適用場景:
1)當創建復雜對象的算法應該獨立于改對象的組成部分以及它們的裝配方式時
2)當構造過程必須允許被構造的對象有不同的表示時
3.UML圖——結構




Director接受一個Builder子類對象,完成創建過程,并通知Builder對象返回以及構造好的產品。
4.效果:
1)可以使你改變一個對象的內部表示
2)構造代碼和表示代碼分開
3)可以對構造過程進行更精細的控制
5。實現:以一個車輛建造過程為例(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
????抽象建造者具有四種方法
????裝配框架
????裝配發動機
????裝配輪子
????裝配車門
????*/
????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";
????????}
????}
????//車輛產品類
????class?Vehicle
????{
????????private?string?type;
????????private?Hashtable?parts?=?new?Hashtable();
????????//筑構函數,決定類型
????????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(?"?發動機?:?"+?parts[?"engine"]?);
????????????Console.WriteLine(?"?#輪子數:?"+?parts[?"wheels"]?);
????????????Console.WriteLine(?"?#車門數?:?"+?parts[?"doors"?]?);
????????}
????}
????///?<summary>
????///?建造者模式應用測試
????///?</summary>
?????class?CarShop
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//?創造車間及車輛建造者
????????????Shop?shop?=?new?Shop();
????????????VehicleBuilder?b1?=?new?ScooterBuilder();
????????????VehicleBuilder?b2?=?new?CarBuilder();
????????????VehicleBuilder?b3?=?new?MotorCycleBuilder();
????????????//?筑構并顯示車輛
????????????shop.Construct(?b1?);
????????????b1.Vehicle.Show();
????????????shop.Construct(?b2?);
????????????b2.Vehicle.Show();
????????????shop.Construct(?b3?);
????????????b3.Vehicle.Show();
????????????Console.Read();
????????}
????}
}
三。Factory Method模式
1.意圖:定義一個用于創建對象的接口,讓子類決定實例化具體的哪一個類。
2.適用場景:
1)當一個類不知道它所必須創建的對象的類的時候,讓子類來決定
2)當一個類希望由它的子類來決定它所創建的對象的時候
3。UML圖——結構:

4.效果:
1)為子類提供回調函數
2)連接平行的類層次
3)?創建函數可以接收參數來決定創建什么產品
4)Factory Method容易導致創建過多的Creator的子類以對應不同的產品,這個方法可以通過模板技術來解決
6.實現,手機工廠,產品可能是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.意圖:通過原型實例指定創建對象的種類,并通過拷貝這些原型來創建新的對象
2.適用場景:
1)要實例化的類是在運行時刻指定的,比如動態裝載
2)為了避免創建一個與產品層次平行的工廠類層次
3)當一個類的實例只能有幾個不同的狀態組合中的一種時,建立相應數目的原型并克隆它們可能比每次用合適的狀態手工化該類更方便一些。
3.UML圖——結構:

4.效果:
1)運行時動態增加或者刪除產品
2)減少子類的構造數目
3)用類動態配置應用
4)動態指定新的對象,通過改變結構或者值
5)缺陷在于每一個Prototype的子類都需要實現clone操作
5。實現,無論java還是C#都從語言層次內置了對prototype模式的支持。具體不再詳述。
五。singleton模式
1。意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點
2.適用場景:
1)當需要類只有一個實例,并且客戶只能通過一個全局點去訪問它
2)當這個唯一實例應該是通過子類化可擴展的,并且客戶應該無需更改代碼就能使用擴展的實例
3.UML圖:略
4.效果:
1)對唯一實例的受控訪問
2)縮小命名空間
3)允許對操作和表示的細化
4)允許可變數目的實例
5實現,關于singleton在java多線程環境下的實現,請見討論《
當Singleton遇到multi-threading》,C#對singleton多線程環境下的能夠正確實現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;
????????}
????}
}
本文僅作速查記憶用,摘記于《設計模式——可復用面向對象軟件基礎》和《深入淺出設計模式(java C#)》兩書