經(jīng)典文檔-C#設(shè)計模式_第1頁
經(jīng)典文檔-C#設(shè)計模式_第2頁
經(jīng)典文檔-C#設(shè)計模式_第3頁
經(jīng)典文檔-C#設(shè)計模式_第4頁
經(jīng)典文檔-C#設(shè)計模式_第5頁
已閱讀5頁,還剩216頁未讀 繼續(xù)免費閱讀

付費下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

C#設(shè)計模式〔10〕 4一、

C#面向?qū)ο蟪绦蛟O(shè)計復習 5二、

設(shè)計模式舉例 5三、

先有雞還是先有蛋? 7四、

大瓶子套小瓶子還是小瓶子套大瓶子? 8五、

.net本質(zhì) 9C#設(shè)計模式〔2〕 11一、"開放-封閉"原那么(OCP) 12二、里氏代換原那么〔LSP〕 12C#設(shè)計模式〔3〕 19三、

依賴倒置原那么(DIP) 19四、

接口隔離原那么〔ISP〕 20五、

合成/聚合復用原那么〔CARP〕 21六、

迪米特法那么〔LoD〕 22C#設(shè)計模式〔4〕-SimpleFactoryPattern 24一、

簡單工廠〔SimpleFactory〕模式 24二、

SimpleFactory模式角色與結(jié)構(gòu): 24三、程序舉例: 25四、

SimpleFactory模式演化 27五、

優(yōu)點與缺點: 29C#設(shè)計模式〔5〕-FactoryMethodPattern 30一、

工廠方法〔FactoryMethod〕模式 30二、

FactoryMethod模式角色與結(jié)構(gòu): 30三、

程序舉例: 31四、

工廠方法模式與簡單工廠模式 33五、

FactoryMethod模式演化 34六、

FactoryMethod模式與其它模式的關(guān)系 35七、

另外一個例子 35C#設(shè)計模式〔6〕-AbstractFactoryPattern 38一、

抽象工廠〔AbstractFactory〕模式 38二、

AbstractFactory模式的結(jié)構(gòu): 39三、

程序舉例: 41四、

在什么情形下使用抽象工廠模式: 44五、

抽象工廠的起源 45六、

AbstractFactory模式在實際系統(tǒng)中的實現(xiàn) 46七、

"開放-封閉"原那么 50C#設(shè)計模式〔7〕-SingletonPattern 50一、

單例〔Singleton〕模式 50二、

Singleton模式的結(jié)構(gòu): 51三、

程序舉例: 51四、

在什么情形下使用單例模式: 52五、

Singleton模式在實際系統(tǒng)中的實現(xiàn) 53六、

C#中的Singleton模式 55C#設(shè)計模式〔8〕-BuilderPattern 57一、

建造者〔Builder〕模式 57二、

Builder模式的結(jié)構(gòu): 58三、

程序舉例: 58四、

建造者模式的活動序列: 62五、

建造者模式的實現(xiàn): 62六、

建造者模式的演化 68七、

在什么情況下使用建造者模式 69C#設(shè)計模式〔9〕-PrototypePattern 70一、

原型〔Prototype〕模式 70二、

Prototype模式的結(jié)構(gòu): 71三、

程序舉例: 71四、

帶PrototypeManager的原型模式 73五、

淺拷貝與深拷貝 77六、

Prototype模式的優(yōu)點與缺點 79C#設(shè)計模式〔10〕-AdapterPattern 80一、

適配器〔Adapter〕模式 80二、

類的Adapter模式的結(jié)構(gòu): 81三、

類的Adapter模式示意性實現(xiàn): 81四、

對象的Adapter模式的結(jié)構(gòu): 83五、

對象的Adapter模式示意性實現(xiàn): 84六、

在什么情況下使用適配器模式 85七、

一個實際應(yīng)用Adapter模式的例子 85八、

關(guān)于Adapter模式的討論 87C#設(shè)計模式〔11〕-CompositePattern 88一、

合成〔Composite〕模式 88二、

合成模式概述 88三、

平安式的合成模式的結(jié)構(gòu) 90四、

平安式的合成模式實現(xiàn) 91五、

透明式的合成模式結(jié)構(gòu) 93六、

透明式的合成模式實現(xiàn) 94七、

使用合成模式時考慮的幾個問題 97八、

和尚的故事 98九、

一個實際應(yīng)用Composite模式的例子 98C#設(shè)計模式〔12〕-DecoratorPattern 101一、

裝飾〔Decorator〕模式 101二、

裝飾模式的結(jié)構(gòu) 102三、

裝飾模式例如性代碼 103四、

裝飾模式應(yīng)當在什么情況下使用 106五、

裝飾模式實際應(yīng)用的例子 106六、

使用裝飾模式的優(yōu)點和缺點 110七、

模式實現(xiàn)的討論 111八、

透明性的要求 111九、

裝飾模式在.NET中的應(yīng)用 112C#設(shè)計模式〔13〕-ProxyPattern 113一、

代理〔Proxy〕模式 113二、

代理的種類 114三、

遠程代理的例子 114四、

代理模式的結(jié)構(gòu) 115五、

代理模式例如性代碼 115六、

高老莊悟空降八戒 117七、

不同類型的代理模式 118八、

代理模式實際應(yīng)用的例子 119設(shè)計模式〔14〕-FlyweightPattern 122一、

享元〔Flyweight〕模式 122二、

單純享元模式的結(jié)構(gòu) 122三、

單純享元模式的示意性源代碼 123四、

復合享元模式的結(jié)構(gòu) 125五、

一個咖啡攤的例子 127六、

咖啡屋的例子 130七、

享元模式應(yīng)當在什么情況下使用 133八、

享元模式的優(yōu)點和缺點 134設(shè)計模式〔15〕-FacadePattern 134一、

門面〔Facade〕模式 134二、

門面模式的結(jié)構(gòu) 134三、

門面模式的實現(xiàn) 135四、

在什么情況下使用門面模式 135五、

一個例子 136六、

使用門面模式的設(shè)計 140設(shè)計模式〔16〕-BridgePattern 144一、

橋梁〔Bridge〕模式 144二、

橋梁模式的結(jié)構(gòu) 145三、

橋梁模式的示意性源代碼 146四、

調(diào)制解調(diào)器問題 149五、

另外一個實際應(yīng)用Bridge模式的例子 153六、

在什么情況下應(yīng)當使用橋梁模式 158設(shè)計模式〔17〕-ChainofResponsibilityPattern 158一、

職責鏈〔ChainofResponsibility〕模式 160二、

責任鏈模式的結(jié)構(gòu) 160三、

責任鏈模式的示意性源代碼 160四、

純的與不純的責任鏈模式 163五、

責任鏈模式的實際應(yīng)用案例 163六、

責任鏈模式的實現(xiàn) 168設(shè)計模式〔18〕-CommandPattern 168一、

命令〔Command〕模式 168二、

命令模式的結(jié)構(gòu) 168三、

命令模式的示意性源代碼 169四、

玉帝傳美猴王上天 172五、

命令模式的實現(xiàn) 172六、

命令模式的實際應(yīng)用案例 173七、

在什么情況下應(yīng)當使用命令模式 177八、

使用命令模式的優(yōu)點和缺點 178設(shè)計模式〔19〕-ObserverPattern 178一、

觀察者〔Observer〕模式 178二、

觀察者模式的結(jié)構(gòu) 179三、

觀察者模式的示意性源代碼 180四、

C#中的Delegate與Event 183五、

一個實際應(yīng)用觀察者模式的例子 187六、

觀察者模式的優(yōu)缺點 191設(shè)計模式〔20〕-VisitorPattern 192一、

訪問者〔Visitor〕模式 192二、

訪問者模式的結(jié)構(gòu) 193三、

示意性源代碼 194四、

一個實際應(yīng)用Visitor模式的例子 198五、

在什么情況下應(yīng)當使用訪問者模式 202六、

使用訪問者模式的優(yōu)點和缺點 203設(shè)計模式〔21〕-TemplateMethodPattern 204一、

模板方法〔TemplateMethod〕模式 204二、

模版方法模式的結(jié)構(gòu) 204三、

模板方法模式的示意性代碼 205四、

繼承作為復用的工具 207五、

一個實際應(yīng)用模板方法的例子 208六、

模版方法模式中的方法 210七、

重構(gòu)的原那么 211設(shè)計模式〔22〕-StrategyPattern 211一、

策略〔Strategy〕模式 211二、

策略模式的結(jié)構(gòu) 212三、

示意性源代碼 212四、

何時使用何種具體策略角色 215五、

一個實際應(yīng)用策略模式的例子 215六、

在什么情況下應(yīng)當使用策略模式 218七、

策略模式的優(yōu)點和缺點 218八、

其它 2196058.html"C#設(shè)計模式〔1〕

課本:?C#設(shè)計模式?,電子工業(yè)出版社,ISBN7-5053-8979-3。33元含光盤。課程內(nèi)容:設(shè)計模式來源:亞歷山大的建筑模式、Gamma等人〔1995〕創(chuàng)作的"DesignPatterns:ElementsofReusableSoftware"。這本書通常被稱作"GangofFour"或"GoF",開創(chuàng)性的創(chuàng)造了?設(shè)計模式?。也有人說"三十六計"就是"模式"。

一、

C#面向?qū)ο蟪绦蛟O(shè)計復習

點擊

二、

設(shè)計模式舉例在設(shè)計模式中有一種模式叫Builder模式,其原理如下:我們可以將Builder理解成電飯鍋,給這個Builder放進去米和水,經(jīng)過Builder的Build后,我們就可以取出香噴噴的米飯了。

C#中有一個類叫StringBuilder,輸入必要的信息后,就可以取出對應(yīng)的String。其使用方法如下:using

System;

using

System.Text;

class

Exam

{

public

static

void

Main()

{

StringBuilder

sb

=

new

StringBuilder();

sb.Append('a',2);

sb.Append('b',3);

sb.Append('c',4);

Console.WriteLine(sb.ToString());

//打印出

aabbbcccc

sb.Remove(0,

sb.Length);

//去除sb中的所有信息

}

}程序執(zhí)行結(jié)果為:aabbbcccc

請使用StringBuilder對以下打印三角型的程序進行改寫,寫出新程序。using

System;

public

class

Exam

{

public

static

void

Main()

{

Console.Write("請輸入行數(shù):");

int

lines

=

int.Parse(Console.ReadLine());

Console.WriteLine("");

for(int

i=1;

i<=lines

;

i++)

{

for(int

k=1;

k<=

lines-i;

k++)

Console.Write("

");

for(int

j=1;

j<=i*2-1;

j++)

Console.Write("*");

Console.WriteLine("");

}

}

}答:using

System;

using

System.Text;

class

Exam

{

public

static

void

Main()

{

Console.Write("請輸入行數(shù):");

int

lines

=

int.Parse(Console.ReadLine());

Console.WriteLine("");

StringBuilder

sb

=

new

StringBuilder();

for(int

i=1;

i<=lines

;

i++)

{

sb.Append('

',

lines-i);

sb.Append('*',

i*2-1);

Console.WriteLine(sb.ToString());

sb.Remove(0,

sb.Length);

}

}

}

三、

先有雞還是先有蛋?到底是先有雞還是先有蛋?看下面的代碼:using

System;

class

Client

{

public

static

void

Main

()

{

Base

b

=

new

Base();

Derived

d

=

new

Derived();

b.d

=

d;

Console.WriteLine(b.d.m);

}

}

class

Base

{

public

int

n

=

9;

public

Derived

d;

}

class

Derived

:

Base

{

public

int

m

=

10;

}Derived繼承自Base,可以說沒有Base就沒有Derived,可Base里面有一個成員是Derived類型。到底是先有雞還是先有蛋?這個程序可以正常編譯執(zhí)行并打印結(jié)果10。

四、

大瓶子套小瓶子還是小瓶子套大瓶子?另外一個例子:using

System;

class

Client

{

public

static

void

Main

()

{

A

a

=

new

A();

B

b

=

new

B();

a.b

=

b;

b.a

=

a;

}

}

class

A

{

public

B

b;

}

class

B

{

public

A

a;

}上面的代碼似乎描述了"a包含b,b包含a"的關(guān)系,到底是大瓶子套小瓶子還是小瓶子套大瓶子呢?

五、

.net本質(zhì)關(guān)于"先有雞還是先有蛋"的程序,系統(tǒng)運行后,內(nèi)存結(jié)構(gòu)如下:

由圖中可以看出,根本不存在雞與蛋的問題,而是型與值的問題以及指針引用的問題。關(guān)于"大瓶子套小瓶子還是小瓶子套大瓶子"問題,系統(tǒng)運行后,內(nèi)存結(jié)構(gòu)如下:

由于是指針引用,所以也無所謂大瓶子還是小瓶子了。關(guān)于更多內(nèi)容可以參考?.NET本質(zhì)論第1卷:公共語言運行庫?。C#設(shè)計模式〔2〕?人月神話?焦油坑、沒有銀彈

*軟件腐化的原因:問題所在

設(shè)計目標

過于僵硬

可擴展性〔新性能可以很容易參加系統(tǒng)〕

過于脆弱

靈活性〔修改不會涉及其它〕

復用率低

粘度過高

可插入性〔新功能容易參加系統(tǒng)〔氣囊參加方向盤〕〕*提高系統(tǒng)可復用性的幾點原那么:

傳統(tǒng)復用:

1.代碼的粘帖復用

2.算法的復用

3.數(shù)據(jù)結(jié)構(gòu)的復用*可維護性與可復用性并不完全一致*對可維護性的支持:

一、"開放-封閉"原那么(OCP)Open-ClosedPrinciple原那么講的是:一個軟件實體應(yīng)當對擴展開放,對修改關(guān)閉。優(yōu)點:

通過擴展已有軟件系統(tǒng),可以提供新的行為,以滿足對軟件的新的需求,使變化中的軟件有一定的適應(yīng)性和靈活性。

已有軟件模塊,特別是最重要的抽象層模塊不能再修改,這使變化中的軟件系統(tǒng)有一定的穩(wěn)定性和延續(xù)性。例子:玉帝招安美猴王

當年大鬧天宮便是美猴王對玉帝的新挑戰(zhàn)。美猴王說:"'皇帝輪流做,明年到我家。'只教他搬出去,將天宮讓于我!"對于這項挑戰(zhàn),太白金星給玉皇大帝提出的建議是:"降一道招安圣旨,宣上界來…,一那么不勞師動眾,二那么收仙有道也。"換而言之,不勞師動眾、不破壞天規(guī)便是"閉",收仙有道便是"開"。招安之道便是玉帝天庭的"開放-封閉"原那么。

招安之法的關(guān)鍵便是不允許更改現(xiàn)有的天庭秩序,但允許將妖猴納入現(xiàn)有秩序中,從而擴展了這一秩序。用面向?qū)ο蟮恼Z言來講,不允許更改的是系統(tǒng)的抽象層,而允許更改的是系統(tǒng)的實現(xiàn)層。

二、里氏代換原那么〔LSP〕LiskovSubstitutionPrinciple〔里氏代換原那么〕:子類型(subtype)必須能夠替換它們的基類型。白馬、黑馬

反過來的代換不成立

?墨子·小取?說:"娣,美人也,愛娣,非愛美人也……"娣便是妹妹,哥哥喜愛妹妹,是因為兩人是兄妹關(guān)系,而不是因為妹妹是個美人。因此,喜愛妹妹不等同于喜愛美人。用面向?qū)ο笳Z言描述,美人是基類,妹妹是美人的子類。哥哥作為一個有"喜愛()"方法,接受妹妹作為參數(shù)。那么,這個"喜愛()"方法一般不能接受美人的實例。

一個違反LSP的簡單例子〔長方形和正方形〕public

class

Rectangle

{

private

long

width;

private

long

height;

public

void

setWidth(long

width)

{

this.width

=

width;

}

public

long

getWidth()

{

return

this.width;

}

public

void

setHeight(long

height)

{

this.height

=

height;

}

public

long

getHeight()

{

return

this.height;

}

}

public

class

Square

{

private

long

side;

public

void

setSide(long

side)

{

this.side

=

side;

}

public

long

getSide()

{

return

side;

}

}

正方形不可以做長方形的子類using

System;

public

class

Rectangle

{

private

long

width;

private

long

height;

public

void

setWidth(long

width)

{

this.width

=

width;

}

public

long

getWidth()

{

return

this.width;

}

public

void

setHeight(long

height)

{

this.height

=

height;

}

public

long

getHeight()

{

return

this.height;

}

}

public

class

Square

:

Rectangle

{

private

long

side;

public

void

setWidth(long

width)

{

setSide(width);

}

public

long

getWidth()

{

return

getSide();

}

public

void

setHeight(long

height)

{

setSide(height);

}

public

long

getHeight()

{

return

getSide();

}

public

long

getSide()

{

return

side;

}

public

void

setSide(long

side)

{

this.side

=

side;

}

}

public

class

SmartTest

{

public

void

resize(Rectangle

r)

{

while

(r.getHeight()

>=

r.getWidth()

)

{

r.setWidth(r.getWidth()

+

1);

}

}

}

在執(zhí)行SmartTest的resize方法時,如果傳入的是長方形對象,當高度大于寬度時,會自動增加寬度直到超出高度。但是如果傳入的是正方形對象,那么會陷入死循環(huán)。代碼重構(gòu)public

interface

Quadrangle

{

public

long

getWidth();

public

long

getHeight();

}

public

class

Rectangle

:

Quadrangle

{

private

long

width;

private

long

height;

public

void

setWidth(long

width)

{

this.width

=

width;

}

public

long

getWidth()

{

return

this.width;

}

public

void

setHeight(long

height)

{

this.height

=

height;

}

public

long

getHeight()

{

return

this.height;

}

}

public

class

Square

:

Quadrangle

{

private

long

side;

public

void

setSide(long

side)

{

this.side

=

side;

}

public

long

getSide()

{

return

side;

}

public

long

getWidth()

{

return

getSide();

}

public

long

getHeight()

{

return

getSide();

}

}

C#設(shè)計模式〔3〕三、

依賴倒置原那么(DIP)依賴倒置〔DependenceInversionPrinciple〕原那么講的是:要依賴于抽象,不要依賴于具體。簡單的說,依賴倒置原那么要求客戶端依賴于抽象耦合。原那么表述:抽象不應(yīng)當依賴于細節(jié);細節(jié)應(yīng)當依賴于抽象;

要針對接口編程,不針對實現(xiàn)編程。反面例子:

缺點:耦合太緊密,Light發(fā)生變化將影響ToggleSwitch。解決方法一:

將Light作成Abstract,然后具體類繼承自Light。

優(yōu)點:ToggleSwitch依賴于抽象類Light,具有更高的穩(wěn)定性,而BulbLight與TubeLight繼承自Light,可以根據(jù)"開放-封閉"原那么進行擴展。只要Light不發(fā)生變化,BulbLight與TubeLight的變化就不會涉及ToggleSwitch。缺點:如果用ToggleSwitch控制一臺電視就很困難了??偛荒茏孴V繼承自Light吧。解決方法二:

優(yōu)點:更為通用、更為穩(wěn)定。結(jié)論:

使用傳統(tǒng)過程化程序設(shè)計所創(chuàng)立的依賴關(guān)系,策略依賴于細節(jié),這是糟糕的,因為策略受到細節(jié)改變的影響。依賴倒置原那么使細節(jié)和策略都依賴于抽象,抽象的穩(wěn)定性決定了系統(tǒng)的穩(wěn)定性。四、

接口隔離原那么〔ISP〕接口隔離原那么〔InterfaceSegregationPrinciple〕講的是:使用多個專門的接口比使用單一的總接口總要好。換而言之,從一個客戶類的角度來講:一個類對另外一個類的依賴性應(yīng)當是建立在最小接口上的。過于臃腫的接口是對接口的污染。不應(yīng)該強迫客戶依賴于它們不用的方法。Myobject-orientedumbrella〔摘自DesignPatternsExplained〕Letmetellyouaboutmygreatumbrella.Itislargeenoughtogetinto!Infact,threeorfourotherpeoplecangetinitwithme.Whileweareinit,stayingoutoftherain,Icanmoveitfromoneplacetoanother.IthasastereosystemtokeepmeentertainedwhileIstaydry.Amazinglyenough,itcanalsoconditiontheairtomakeitwarmerorcolder.Itisonecoolumbrella.Myumbrellaisconvenient.Itsitstherewaitingforme.IthaswheelsonitsothatIdonothavetocarryitaround.Idon'tevenhavetopushitbecauseitcanpropelitself.Sometimes,Iwillopenthetopofmyumbrellatoletinthesun.(WhyIamusingmyumbrellawhenitissunnyoutsideisbeyondme!)InSeattle,therearehundredsofthousandsoftheseumbrellasinallkindsofcolors.Mostpeoplecallthemcars.實現(xiàn)方法:

1、

使用委托別離接口

2、

使用多重繼承別離接口五、

合成/聚合復用原那么〔CARP〕合成/聚合復用原那么〔Composite/AggregateReusePrinciple或CARP〕經(jīng)常又叫做合成復用原那么〔CompositeReusePrinciple或CRP〕,就是在一個新的對象里面使用一些已有的對象,使之成為新對象的一局部;新對象通過向這些對象的委派到達復用已有功能的目的。簡而言之,要盡量使用合成/聚合,盡量不要使用繼承。oDesigntointerfaces.

oFavorcompositionoverinheritance.

oFindwhatvariesandencapsulateit.

〔摘自:DesignPatternsExplained〕區(qū)分"Has-A"與"Is-A""Is-A"是嚴格的分類學意義上定義,意思是一個類是另一個類的"一種"。而"Has-A"那么不同,它表示某一個角色具有某一項責任。導致錯誤的使用繼承而不是合成/聚合的一個常見的原因是錯誤的把"Has-A"當作"Is-A"。例如:

實際上,雇員、經(jīng)理、學生描述的是一種角色,比方一個人是"經(jīng)理"必然是"雇員",另外一個人可能是"學生雇員",在上面的設(shè)計中,一個人無法同時擁有多個角色,是"雇員"就不能再是"學生"了,這顯然是不合理的。錯誤源于把"角色"的等級結(jié)構(gòu)與"人"的等級結(jié)構(gòu)混淆起來,誤把"Has-A"當作"Is-A"。解決方法:

六、

迪米特法那么〔LoD〕迪米特法那么〔LawofDemeter或簡寫LoD〕又叫最少知識原那么〔LeastKnowledgePrinciple或簡寫為LKP〕,也就是說,一個對象應(yīng)當對其它對象有盡可能少的了解。其它表述:

只與你直接的朋友們通信

不要跟"陌生人"說話

每一個軟件單位對其它的單位都只有最少的知識,而且局限于那些與本單位密切相關(guān)的軟件單位。迪米特法那么與設(shè)計模式

Facade模式、Mediator模式使民無知

?老子?第三章曰:"是以圣人之治,虛其心,實其腹,弱其志,常使民無知無欲。"使被"統(tǒng)治"的對象"愚昧"化,處于"無知"的狀態(tài),可以使"統(tǒng)治"的本錢降低。

所謂"最少知識"原那么,實際上便是老子的"使民無知"的統(tǒng)治之術(shù)。不相往來

?老子?云:"小國寡民……鄰國相望,雞犬之聲相聞,民至老死,不相往來。"將被統(tǒng)治的對象隔離開來,使它們沒有直接的通信,可以到達分化瓦解,繼而分而治之的效果。迪米特法那么與老子的"小國寡民"的統(tǒng)治之術(shù)不謀而合。C#設(shè)計模式〔4〕-SimpleFactoryPattern工廠模式專門負責將大量有共同接口的類實例化。工廠模式可以動態(tài)決定將哪一個類實例化,不必事先知道每次要實例化哪一個類。工廠模式有以下幾種形態(tài):簡單工廠〔SimpleFactory〕模式工廠方法〔FactoryMethod〕模式抽象工廠〔AbstractFactory〕模式

一、

簡單工廠〔SimpleFactory〕模式SimpleFactory模式根據(jù)提供應(yīng)它的數(shù)據(jù),返回幾個可能類中的一個類的實例。通常它返回的類都有一個公共的父類和公共的方法。SimpleFactory模式實際上不是GoF23個設(shè)計模式中的一員。

二、

SimpleFactory模式角色與結(jié)構(gòu):

工廠類角色Creator(LightSimpleFactory):工廠類在客戶端的直接控制下〔Create方法〕創(chuàng)立產(chǎn)品對象。

抽象產(chǎn)品角色Product(Light):定義簡單工廠創(chuàng)立的對象的父類或它們共同擁有的接口??梢允且粋€類、抽象類或接口。

具體產(chǎn)品角色ConcreteProduct(BulbLight,TubeLight):定義工廠具體加工出的對象。

三、程序舉例:using

System;

public

abstract

class

Light

{

public

abstract

void

TurnOn();

public

abstract

void

TurnOff();

}

public

class

BulbLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Bulb

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Bulb

Light

is

Turned

off");

}

}

public

class

TubeLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Tube

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Tube

Light

is

Turned

off");

}

}

public

class

LightSimpleFactory

{

public

Light

Create(string

LightType)

{

if(LightType

==

"Bulb")

return

new

BulbLight();

else

if(LightType

==

"Tube")

return

new

TubeLight();

else

return

null;

}

}

public

class

Client

{

public

static

void

Main()

{

LightSimpleFactory

lsf

=

new

LightSimpleFactory();

Light

l

=

lsf.Create("Bulb");

l.TurnOn();

l.TurnOff();

Console.WriteLine("");

l

=

lsf.Create("Tube");

l.TurnOn();

l.TurnOff();

}

}四、

SimpleFactory模式演化SimpleFactory模式演化〔一〕除了上面的用法外,在有些情況下SimpleFactory可以由抽象產(chǎn)品角色扮演,一個抽象產(chǎn)品類同時是子類的工廠。程序舉例:using

System;

public

class

Light

{

public

virtual

void

TurnOn()

{

}

public

virtual

void

TurnOff()

{

}

public

static

Light

Create(string

LightType)

{

if(LightType

==

"Bulb")

return

new

BulbLight();

else

if(LightType

==

"Tube")

return

new

TubeLight();

else

return

null;

}

}

public

class

BulbLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Bulb

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Bulb

Light

is

Turned

off");

}

}

public

class

TubeLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Tube

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Tube

Light

is

Turned

off");

}

}

public

class

Client

{

public

static

void

Main()

{

Light

l

=

Light.Create("Bulb");

l.TurnOn();

l.TurnOff();

Console.WriteLine("");

l

=

Light.Create("Tube");

l.TurnOn();

l.TurnOff();

}

}

SimpleFactory模式演化〔二〕三個角色全部合并:

與單件模式〔Singleton〕相近,但是有區(qū)別。

五、

優(yōu)點與缺點:優(yōu)點:

工廠類含有必要的判斷邏輯,可以決定在什么時候創(chuàng)立哪一個產(chǎn)品類的實例,客戶端可以免除直接創(chuàng)立產(chǎn)品對象的責任,而僅僅"消費"產(chǎn)品。簡單工廠模式通過這種做法實現(xiàn)了對責任的分割。缺點:

當產(chǎn)品有復雜的多層等級結(jié)構(gòu)時,工廠類只有自己,以不變應(yīng)萬變,就是模式的缺點。因為工廠類集中了所有產(chǎn)品創(chuàng)立邏輯,一旦不能正常工作,整個系統(tǒng)都要受到影響。同時,系統(tǒng)擴展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯,有可能造成工廠邏輯過于復雜。另外,簡單工廠模式通常使用靜態(tài)工廠方法,這使得無法由子類繼承,造成工廠角色無法形成基于繼承的等級結(jié)構(gòu)。C#設(shè)計模式〔5〕-FactoryMethodPattern一、

工廠方法〔FactoryMethod〕模式工廠方法〔FactoryMethod〕模式是類的創(chuàng)立模式,其用意是定義一個創(chuàng)立產(chǎn)品對象的工廠接口,將實際創(chuàng)立工作推遲到子類中。工廠方法模式是簡單工廠模式的進一步抽象和推廣。由于使用了多態(tài)性,工廠方法模式保持了簡單工廠模式的優(yōu)點,而且克服了它的缺點。在工廠方法模式中,核心的工廠類不再負責所有產(chǎn)品的創(chuàng)立,而是將具體創(chuàng)立工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現(xiàn)的接口,而不接觸哪一個產(chǎn)品類被實例化這種細節(jié)。這使得工廠方法模式可以允許系統(tǒng)在不修改工廠角色的情況下引進新產(chǎn)品。在FactoryMethod模式中,工廠類與產(chǎn)品類往往具有平行的等級結(jié)構(gòu),它們之間一一對應(yīng)。

二、

FactoryMethod模式角色與結(jié)構(gòu):

抽象工廠〔Creator〕角色:是工廠方法模式的核心,與應(yīng)用程序無關(guān)。任何在模式中創(chuàng)立的對象的工廠類必須實現(xiàn)這個接口。具體工廠〔ConcreteCreator〕角色:這是實現(xiàn)抽象工廠接口的具體工廠類,包含與應(yīng)用程序密切相關(guān)的邏輯,并且受到應(yīng)用程序調(diào)用以創(chuàng)立產(chǎn)品對象。在上圖中有兩個這樣的角色:BulbCreator與TubeCreator。抽象產(chǎn)品〔Product〕角色:工廠方法模式所創(chuàng)立的對象的超類型,也就是產(chǎn)品對象的共同父類或共同擁有的接口。在上圖中,這個角色是Light。具體產(chǎn)品〔ConcreteProduct〕角色:這個角色實現(xiàn)了抽象產(chǎn)品角色所定義的接口。某具體產(chǎn)品有專門的具體工廠創(chuàng)立,它們之間往往一一對應(yīng)。

三、

程序舉例:using

System;

public

abstract

class

Light

{

public

abstract

void

TurnOn();

public

abstract

void

TurnOff();

}

public

class

BulbLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Bulb

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Bulb

Light

is

Turned

off");

}

}

public

class

TubeLight

:

Light

{

public

override

void

TurnOn()

{

Console.WriteLine("Tube

Light

is

Turned

on");

}

public

override

void

TurnOff()

{

Console.WriteLine("Tube

Light

is

Turned

off");

}

}

public

abstract

class

Creator

{

public

abstract

Light

factory();

}

public

class

BulbCreator

:

Creator

{

public

override

Light

factory()

{

return

new

BulbLight();

}

}

public

class

TubeCreator

:

Creator

{

public

override

Light

factory()

{

return

new

TubeLight();

}

}

public

class

Client

{

public

static

void

Main()

{

Creator

c1

=

new

BulbCreator();

Creator

c2

=

new

TubeCreator();

Light

l1

=

c1.factory();

Light

l2

=

c2.factory();

l1.TurnOn();

l1.TurnOff();

Console.WriteLine("");

l2.TurnOn();

l2.TurnOff();

}

}工廠方法的活動序列圖

活動過程包括:客戶端創(chuàng)立BulbCreator對象,客戶端持有此對象的類型是Creator,而實際類型是BulbCreator。然后客戶端調(diào)用BulbCreator的factory方法,之后BulbCreator調(diào)用BulbLight的構(gòu)造函數(shù)創(chuàng)造出產(chǎn)品BulbLight對象。

四、

工廠方法模式與簡單工廠模式工廠方法模式與簡單工廠模式再結(jié)構(gòu)上的不同不是很明顯。工廠方法類的核心是一個抽象工廠類,而簡單工廠模式把核心放在一個具體類上。工廠方法模式之所以有一個別名叫多態(tài)性工廠模式是因為具體工廠類都有共同的接口,或者有共同的抽象父類。當系統(tǒng)擴展需要添加新的產(chǎn)品對象時,僅僅需要添加一個具體對象以及一個具體工廠對象,原有工廠對象不需要進行任何修改,也不需要修改客戶端,很好的符合了"開放-封閉"原那么。而簡單工廠模式在添加新產(chǎn)品對象后不得不修改工廠方法,擴展性不好。工廠方法模式退化后可以演變成簡單工廠模式。

五、

FactoryMethod模式演化使用接口或抽象類

抽象工廠角色和抽象場頻角色都可以選擇由接口或抽象類實現(xiàn)。使用多個工廠方法

抽象工廠角色可以規(guī)定出多于一個的工廠方法,從而使具體工廠角色實現(xiàn)這些不同的工廠方法,這些方法可以提供不同的商業(yè)邏輯,以滿足提供不同的產(chǎn)品對象的任務(wù)。產(chǎn)品的循環(huán)使用

工廠方法總是調(diào)用產(chǎn)品類的構(gòu)造函數(shù)以創(chuàng)立一個新的產(chǎn)品實例,然后將這個實例提供應(yīng)客戶端。而在實際情形中,工廠方法所做的事情可以相當復雜。一個常見的復雜邏輯就是循環(huán)使用產(chǎn)品對象。工廠對象將已經(jīng)創(chuàng)立過的產(chǎn)品登記到一個聚集中,然后根據(jù)客戶所請求的產(chǎn)品狀態(tài),向聚集查詢。如果有滿足要求的產(chǎn)品對象,就直接將產(chǎn)品返回客戶端;如果聚集中沒有這樣的產(chǎn)品對象,那么就創(chuàng)立一個新的滿足要求的產(chǎn)品對象,然后將這個對象登記到聚集中,再返還給客戶端。"享元模式〔FlyweightPattern〕"就是這樣一個模式。

多態(tài)性的喪失和模式的退化

一個工廠方法模式的實現(xiàn)依賴于工廠角色和產(chǎn)品角色的多態(tài)性。在有些情況下,這個模式可以出現(xiàn)退化。工廠方法返回的類型應(yīng)當是抽象類型,而不是具體類型。調(diào)用工廠方法的客戶端應(yīng)當依賴抽象產(chǎn)品編程,而不是具體產(chǎn)品。如果工廠僅僅返回一個具體產(chǎn)品對象,便違背了工廠方法的用意,發(fā)生退化,這時就不再是工廠模式了。工廠的等級結(jié)構(gòu):工廠對象應(yīng)當有一個抽象的超類型。如果等級結(jié)構(gòu)中只有一個具體工廠類的話,抽象工廠就可以省略,發(fā)生了退化。

六、

FactoryMethod模式與其它模式的關(guān)系與工廠方法模式有關(guān)的模式還包括:

模板方法模式、MVC模式、享元模式、備忘錄模式

七、

另外一個例子//

Factory

Method

pattern

--

Real

World

example

using

System;

using

System.Collections;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論