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

下載本文檔

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

文檔簡(jiǎn)介

C#設(shè)計(jì)模式(+Q_)4

一、C#面向?qū)ο蟪绦蛟O(shè)計(jì)復(fù)習(xí)5

二、設(shè)計(jì)模式舉例5

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

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

五、.net本質(zhì)9

C#設(shè)計(jì)模式(2)11

一、"開(kāi)放一封閉"原則(OCP)12

二、里氏代換原則(LSP)12

C#設(shè)計(jì)模式(3)19

三、依賴倒置原則(DIP)19

四、接口隔離原則(ISP)20

五、合成/聚合復(fù)用原則(CARP)21

六、迪米特法則(LoD)22

C#設(shè)計(jì)模式(4)—SimpieFactoryPattern24

一、簡(jiǎn)單工廠(SimpleFactory)模式24

二、SimpieFactory模式角色與結(jié)構(gòu):24

三、程序舉例:25

四、SimpieFactory模式演化27

五、優(yōu)點(diǎn)與缺點(diǎn):29

C#設(shè)計(jì)模式(5)—FactoryMethodPattern30

一、工廠方法(FactoryMethod)模式30

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

三、程序舉例:31

四、工廠方法模式與簡(jiǎn)單工廠模式33

五、FactoryMethod模式演化34

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

七、另外一個(gè)例子35

C#設(shè)計(jì)模式(6)—AbstractFactoryPattern38

一、抽象工廠(AbstractFactory)模式38

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

三、程序舉例:41

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

五、抽象工廠的起源45

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

七、"開(kāi)放一封閉"原則50

C#設(shè)計(jì)模式(7)—SingletonPattern50

一、單例(Singleton)模式50

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

三、程序舉例:51

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

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

六、C#中的Singleton模式55

C#設(shè)計(jì)模式(8)—BuilderPattern57

一、建造者(Builder)模式57

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

三、程序舉例:58

四、建造者模式的活動(dòng)序列:62

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

六、建造者模式的演化68

七、在什么情況下使用建造者模式69

C#設(shè)計(jì)模式(9)-PrototypePattern70

一、原型(Prototype)模式70

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

三、程序舉例:71

四、帶PrototypeManager的原型模式73

五、淺拷貝與深拷貝77

六、Prototype模式的優(yōu)點(diǎn)與缺點(diǎn)79

C#設(shè)計(jì)模式(10)—AdapterPattern80

一、適配器(Adapter)模式80

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

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

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

五、對(duì)象的Adapter模式示意性實(shí)現(xiàn):84

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

七、一個(gè)實(shí)際應(yīng)用Adapter模式的例子85

八、關(guān)于Adapter模式的討論87

C#設(shè)計(jì)模式(11)—CompositePattern88

一、合成(Composite)模式88

二、合成模式概述88

三、安全式的合成模式的結(jié)構(gòu)8990

四、安全式的合成模式實(shí)現(xiàn)90W-

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

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

七、使用合成模式時(shí)考慮的幾個(gè)問(wèn)題97

八、和尚的故事9798

九、一^1V實(shí)際應(yīng)用Composite模式的例子98

C#設(shè)計(jì)模式(12)—DecoratorPattern101

一、裝飾(Decorator)模式101

二、裝飾模式的結(jié)構(gòu)KM4O2

三、裝飾模式示例性代碼102403

四、裝飾模式應(yīng)當(dāng)在什么情況下使用105-W6

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

六、使用裝飾模式的優(yōu)點(diǎn)和缺點(diǎn)110

七、模式實(shí)現(xiàn)的討論H0++4-

八、透明性的要求111

九、裝飾模式在.NET中的應(yīng)用112

C#設(shè)計(jì)模式(13)—ProxyPattern113

一、代理(Proxy)模式113

二、代理的種類114

三、遠(yuǎn)程代理的例子114

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

五、代理模式示例性代碼115

六、高老莊悟空降八戒117

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

八、代理模式實(shí)際應(yīng)用的例子119

設(shè)計(jì)模式(14)—FlyweightPattern122

—?、享元(Flyweight)模式122

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

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

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

五、一個(gè)咖啡攤的例子127

六、咖啡屋的例子130

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

八、享元模式的優(yōu)點(diǎn)和缺點(diǎn)133434

設(shè)計(jì)模式(15)-FacadePattern134

―■、門面(Facade)模式134

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

三、門面模式的實(shí)現(xiàn)135

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

五、一個(gè)例子136

六、使用門面模式的設(shè)計(jì)140

設(shè)計(jì)模式(16)—BridgePattern144

一、橋梁(Bridge)模式144

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

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

四、調(diào)制解調(diào)器問(wèn)題149

五、另外一個(gè)實(shí)際應(yīng)用Bridge模式的例子153

六、在什么情況下應(yīng)當(dāng)使用橋梁模式158

設(shè)計(jì)模式(17)—ChainofResponsibilityPattern158

一、職責(zé)鏈(ChainofResponsibility)模式160

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

三、責(zé)任鏈模式的示意性源代碼160

四、純的與不純的責(zé)任鏈模式163

五、責(zé)任鏈模式的實(shí)際應(yīng)用案例163

六、責(zé)任鏈模式的實(shí)現(xiàn)168

設(shè)計(jì)模式(18)—CommandPattern168

一、命令(Command)模式168

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

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

四、玉帝傳美猴王上天172

五、命令模式的實(shí)現(xiàn)172

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

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

八、使用命令模式的優(yōu)點(diǎn)和缺點(diǎn)178

設(shè)計(jì)模式(19)—ObserverPattern178

一、觀察者(Observer)模式178

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

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

四、C#中的Delegate與Event183

五、一個(gè)實(shí)際應(yīng)用觀察者模式的例子187

六、觀察者模式的優(yōu)缺點(diǎn)191

設(shè)計(jì)模式(20)-VisitorPattern192

一、訪問(wèn)者(Visitor)模式192

二、訪問(wèn)者模式的結(jié)構(gòu)193

三、示意性源代碼194

四、一個(gè)實(shí)際應(yīng)用Visitor模式的例子198

五、在什么情況下應(yīng)當(dāng)使用訪問(wèn)者模式202

六、使用訪問(wèn)者模式的優(yōu)點(diǎn)和缺點(diǎn)203

設(shè)計(jì)模式(21)—TemplateMethodPattern204

一、模板方法(TemplateMethod)模式204

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

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

四、繼承作為復(fù)用的工具207

五、一個(gè)實(shí)際應(yīng)用模板方法的例子208

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

七、重構(gòu)的原則211

設(shè)計(jì)模式(22)—StrategyPattern211

一、策略(Strategy)模式211

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

三、示意性源代碼212

四、何時(shí)使用何種具體策略角色215

五、一個(gè)實(shí)際應(yīng)用策略模式的例子215

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

七、策略模式的優(yōu)點(diǎn)和缺點(diǎn)218

八、其它219

C#設(shè)計(jì)模式(1)

課本:《0#設(shè)計(jì)模式》,電子工業(yè)出版社,ISBN7-5053-8979-3033元含光盤。

課程內(nèi)容:設(shè)計(jì)模式

來(lái)源:亞歷山大的建筑模式、Gamma等人(1995)創(chuàng)作的"DesignPatterns:Elementsof

ReusableSoftware".這本書(shū)通常被稱作"GangofFour"或"GoF",開(kāi)創(chuàng)性的創(chuàng)造了《設(shè)計(jì)

模式》。

也有人說(shuō)"三十六計(jì)"就是"模式"。

一、C#面向?qū)ο蟪绦蛟O(shè)計(jì)復(fù)習(xí)

點(diǎn)擊/Files/zhenyulu/CSharp.rar下載,內(nèi)容包括:

字段與屬性.cs

屬性、方法作用范圍.CS

-加到一百.CS

使用接口排序(2).CS

使用接口排序(1).CS

求質(zhì)數(shù).cs

冒泡法排序.cs

九九表.cs

靜態(tài)與非靜態(tài).cs

構(gòu)造函數(shù).cs

方法重載.cs

多態(tài)性.cs

遞歸求階乘.cs

打印三角形.cs

傳值調(diào)用與引用調(diào)用.cs

二、設(shè)計(jì)模式舉例

在設(shè)計(jì)模式中有一種模式叫Builder模式,其原理如下:

我們可以將Builder理解成電飯鍋,給這個(gè)Builder放進(jìn)去米和水,經(jīng)過(guò)Builder的Build后,

我們就可以取出香噴噴的米飯了。

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

如下:

usingSystem;

usingSystem.Text;

classExam

0S{

publicstaticvoidMain()

白由(

StringBuildersb=newStringBuilder();

sb.Append('a',2);

sb.Append('b',3);

sb.Append('c',4);

IConsole.WriteLine(sb.ToStringO);〃打印出aabbbcccc

Isb.Remove(0,sb.Length);〃清除sb中的所有信息

卜}

L)

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

請(qǐng)使用StringBuilder對(duì)以下打印三角型的程序進(jìn)行改寫,寫出新程序。

usingSystem;

publicclassExam

日叫

publicstaticvoidMain()

白由(

IConsole.Write(”請(qǐng)輸入行數(shù):“);

intlines=int.Parse(Console.ReadLine());

IConsole.WriteLine(n");

Ifor(inti=1;i<=lines;i++)

均由{

for(intk=1;k<=lines-i;k++)

IConsole.Write(M");

Ifor(intj=1;j<=i*2-1;j++)

IConsole.Write(u*");

IConsole.WriteLine(,M,);

卜)

卜}

L}

答:

usingSystem;

usingSystem.Text;

classExam

日期

publicstaticvoidMain()

附{

IConsole.Write("請(qǐng)輸入行數(shù):");

intlines=int.Parse(Console.ReadLine());

IConsole.WriteLine("");

I

StringBuildersb=newStringBuilder();

I

for(inti=1;i<=lines;i++)

白由(

sb.Append('lines-i);

Isb.AppendC*',i*2-1);

Console.WriteLine(sb.ToString());

sb.Remove(0,sb.Length);

卜}

b

三、先有雞還是先有蛋?

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

usingSystem;

classClient

publicstaticvoidMain()

的中{

Baseb=newBase();

Derivedd=newDerived();

Ib.d=d;

Console.WriteLine(b.d.m);

卜)

classBase

日期

publicintn=9;

publicDerivedd;

L)

classDerived:Base

日叫

publicintm=10;

Derived繼承自Base,可以說(shuō)沒(méi)有Base就沒(méi)有Derived,可Base里面有一個(gè)成員是Derived

類型。到底是先有雞還是先有蛋?這個(gè)程序可以正常編譯執(zhí)行并打印結(jié)果10。

四、大瓶子套小瓶子還是小瓶子套大瓶子?

另外一個(gè)例子:

usingSystem;

classClient

日出{

publicstaticvoidMain()

心由(

Aa=newA();

Bb=newB();

a.b=b;

b.a=a;

卜)

L)

classA

□S(

publicBb;

L)

classB

日叫

publicAa;

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

子呢?

五、.net本質(zhì)

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

Base

Derived

由圖中可以看出,根本不存在雞與蛋的問(wèn)題,而是型與值的問(wèn)題以及指針引用的問(wèn)題。

關(guān)于"大瓶子套小瓶子還是小瓶子套大瓶子"問(wèn)題,系統(tǒng)運(yùn)行后,內(nèi)存結(jié)構(gòu)如下:

CORINFO_CLASS?STRUCT

由于是指針引用,所以也無(wú)所謂大瓶子還是小瓶子了。

關(guān)于更多內(nèi)容可以參考《.NET本質(zhì)論第1卷:公共語(yǔ)言運(yùn)行庫(kù)》。

C#設(shè)計(jì)模式(2)

《人月神話》焦油坑、沒(méi)有銀彈

*軟件腐化的原因:

問(wèn)題所在設(shè)計(jì)H標(biāo)

過(guò)于僵硬可擴(kuò)展性(新性能可以很容易加入系統(tǒng))

過(guò)于脆弱靈活性(修改不會(huì)波及其它)

復(fù)用率低

粘度過(guò)高可插入性(新功能容易加入系統(tǒng)(氣囊加入方向盤))

*提高系統(tǒng)可復(fù)用性的幾點(diǎn)原則:

傳統(tǒng)復(fù)用:

1.代碼的粘帖復(fù)用

2.算法的復(fù)用

3.數(shù)據(jù)結(jié)構(gòu)的復(fù)用

*可維護(hù)性與可復(fù)用性并不完全一致

對(duì)可維護(hù)性的支持:

一、”開(kāi)放一封閉”原貝U(OCP)

Open-ClosedPrinciple原則講的是:一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。

優(yōu)點(diǎn):

通過(guò)擴(kuò)展已有軟件系統(tǒng),可以提供新的行為,以滿足對(duì)軟件的新的需求,使變化中的軟件有

一定的適應(yīng)性和靈活性。

已有軟件模塊,特別是最重要的抽象層模塊不能再修改,這使變化中的軟件系統(tǒng)有一定的穩(wěn)

定性和延續(xù)性。

例子:玉帝招安美猴王

當(dāng)年大鬧天宮便是美猴王對(duì)玉帝的新挑戰(zhàn)。美猴王說(shuō):“‘皇帝輪流做,明年到我家?!唤趟岢?/p>

去,將天宮讓于我!"對(duì)于這項(xiàng)挑戰(zhàn),太白金星給玉皇大帝提出的建議是:"降一道招安圣旨,宣

上界來(lái)…,一則不勞師動(dòng)眾,二則收仙有道也。"

換而言之,不勞師動(dòng)眾、不破壞天規(guī)便是"閉",收仙有道便是"開(kāi)"。招安之道便是玉帝天庭的“

開(kāi)放一封閉"原則。

招安之法的關(guān)鍵便是不允許更改現(xiàn)有的天庭秩序,但允許將妖猴納入現(xiàn)有秩序中,從而擴(kuò)展了這

一秩序。用面向?qū)ο蟮恼Z(yǔ)言來(lái)講,不允許更改的是系統(tǒng)的抽象層,而允許更改的是系統(tǒng)的實(shí)現(xiàn)層。

二、里氏代換原則(LSP)

LiskovSubstitutionPrinciple(里氏代換原則):子類型(subtype)必須能夠替換它們的基類

型。

白馬、黑馬

反過(guò)來(lái)的代換不成立

《墨子?小取》說(shuō):“娣,美人也,愛(ài)娣,非愛(ài)美人也…?..”娣便是妹妹,哥哥喜愛(ài)妹妹,是因?yàn)閮?/p>

人是兄妹關(guān)系,而不是因?yàn)槊妹檬莻€(gè)美人。因此,喜愛(ài)妹妹不等同于喜愛(ài)美人。用面向?qū)ο笳Z(yǔ)言

描述,美人是基類,妹妹是美人的子類。哥哥作為一個(gè)有“喜愛(ài)()”方法,接受妹妹作為參數(shù)。那

么,這個(gè)‘喜愛(ài)()”方法?般不能接受美人的實(shí)例。

?個(gè)違反LSP的簡(jiǎn)單例子?(長(zhǎng)方形和正方形)

publicclassRectangle

日日{

privatelongwidth;

privatelongheight;

publicvoidsetWidth(longwidth)

百才(

this.width=width;

卜)

IpubliclonggetWidth()

自由(

Ireturnthis.width;

卜)

publicvoidsetHeight(longheight)

白由(

this.height=height;

卜)

publiclonggetHeight()

的(

returnthis.height;

卜)

4

publicclassSquare

日刊

privatelongside;

I

publicvoidsetSide(longside)

由由(

this.side=side;

卜)

I

publiclonggetSide()

由由(

returnside;

卜)

正方形不可以做長(zhǎng)方形的子類

usingSystem;

publicclassRectangle

日期

privatelongwidth;

privatelongheight;

I

publicvoidsetWidth(longwidth)

白由(

this.width=width;

卜)

IpubliclonggetWidth()

由中{

returnthis.width;

卜)

publicvoidsetHeight(longheight)

的中{

this.height=height;

卜)

publiclonggetHeight()

后由{

returnthis.height;

卜)

4

publicclassSquare:Rectangle

privatelongside;

I

)publicvoidsetWidth(longwidth)

的{

setSide(width);

卜)

I

ipubliclonggetWidth()

白由(

returngetSide();

卜)

publicvoidsetHeight(longheight)

白由(

setSide(height);

卜)

I

publiclonggetHeight()

白由(

returngetSide();

卜)

I

publiclonggetSide()

的{

returnside;

卜)

I

publicvoidsetSide(longside)

由由(

this.side=side;

卜)

publicclassSmartTest

日典

publicvoidresize(Rectangler)

中由{

while(r.getHeight()>=r.getWidth())

白由(

r.setWidth(r.getWidth()+1);

)

RectangleSmartTest

日Hacs冰

-heightJong日Me6ads

-widthJong?resize:void

日Mafxy

?getHeightdong

?getWidthdong

?setHeight:void

+setWidlh:void

A

Square

0fqg

-sideJong

?getHeightdong

?getSideJong

*getWidth:long

?setHeight:void

*setSide:void

+setWidlh:void

在執(zhí)行SmartTest的resize方法時(shí),如果傳入的是長(zhǎng)方形對(duì)象,當(dāng)高度大于寬度時(shí);會(huì)自動(dòng)

增加寬度直到超出高度。但是如果傳入的是正方形對(duì)象,則會(huì)陷入死循環(huán)。

代碼重構(gòu)

publicinterfaceQuadrangle

0S(

IpubliclonggetWidth();

publiclonggetHeight();

publicclassRectangle:Quadrangle

日刊{

privatelongwidth;

privatelongheight;

I

publicvoidsetWidth(longwidth)

心由(

this.width=width;

publiclonggetWidth()

Ireturnthis.width;

卜)

publicvoidsetHeight(longheight)

白由{

this.height=height;

卜)

publiclonggetHeight()

白由(

returnthis.height;

publicclassSquare:Quadrangle

0El{

privatelongside;

I

publicvoidsetSide(longside)

中由{

this.side=side;

publiclonggetSide()

returnside;

publiclonggetWidth()

returngetSide();

publiclonggetHeight()

鐘{

returngetSide();

卜)

L}

interfaceSmartTest

Quadrangle■FtciOfi

口Methods

^getWidth:long+resize:void

^getHeight:long

-Protfertnry

A△

SquareRectangle

□區(qū)疫EJFQNS

-sidelong-height:long

-widthlong

*getHeight:longQMethods

*getSideJong+getHeight:long

+getWidth:long+getWidth:long

?setSide:void+setHeight:void

Pmiienu^+setWidth:void

?Pon)c:tics

C#設(shè)計(jì)模式(3)

三、依賴倒置原則(DIP)

依賴倒置(DependenceInversionPrinciple)原則講的是:要依賴于抽象,不要依賴于具體。

簡(jiǎn)單的說(shuō),依賴倒置原則要求客戶端依賴于抽象耦合。原則表述:

抽象不應(yīng)當(dāng)依賴于細(xì)節(jié);細(xì)節(jié)應(yīng)當(dāng)依賴于抽象;

要針對(duì)接口編程,不針對(duì)實(shí)現(xiàn)編程。

反面例子:

ToggkSwitch

-liglil.Light

+Tog@以)

缺點(diǎn):耦合太緊密,Light發(fā)生變化將影響ToggleSwitch。

解決辦法一:

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

優(yōu)點(diǎn):Toggleswitch依賴于抽象類Light,具有更高的穩(wěn)定性,而B(niǎo)ulbLight與TubeLight

繼承自Light,可以根據(jù)"開(kāi)放一封閉"原則進(jìn)行擴(kuò)展。只要Light不發(fā)生變化,BulbLight與

TubeLight的變化就不會(huì)波及ToggleSwitch。

缺點(diǎn):如果用Toggleswitch控制一臺(tái)電視就很困難了??偛荒茏孴V繼承自Light吧。

解決方法二:

II

JISwitchabkL

Iy-TumOnOVI

I卜TumOfff)II

lojgjIcSwitch

-switchable:ISwitchablc

4-ToggleO

優(yōu)點(diǎn):更為通用、更為穩(wěn)定。

結(jié)論:

使用傳統(tǒng)過(guò)程化程序設(shè)計(jì)所創(chuàng)建的依賴關(guān)系,策略依賴于細(xì)節(jié),這是糟糕的,因?yàn)椴呗允艿郊?xì)門

改變的影響。依賴倒置原則使細(xì)節(jié)和策略都依賴于抽象,抽象的穩(wěn)定性決定了系統(tǒng)的穩(wěn)定性。

四、接口隔離原則(ISP)

接口隔離原則(InterfaceSegregationPrinciple)講的是:使用多個(gè)專門的接口比使用單一

的總接口總要好。換而言之,從一個(gè)客戶類的角度來(lái)講:一個(gè)類對(duì)另外一個(gè)類的依賴性應(yīng)當(dāng)是建

立在最小接口上的。

過(guò)于臃腫的接口是對(duì)接口的污染。不應(yīng)該強(qiáng)迫客戶依賴于它們不用的方法。

Myobject-orientedumbrella(摘自DesignPatternsExplained)

Letmetellyouaboutmygreatumbrella.Itislargeenoughtogetinto!Infact,three

orfourotherpeoplecangetinitwithme.Whileweareinit,stayingoutoftherain,

Icanmoveitfromoneplacetoanother.Ithasastereosystemtokeepme

entertainedwhileIstaydry.Amazinglyenough,itcanalsoconditiontheairtomake

itwarmerorcolder.Itisonecoolumbrella.

Myumbrellaisconvenient.Itsitstherewaitingforme.IthaswheelsonitsothatI

donothavetocarryitaround.Idon'tevenhavetopushitbecauseitcanpropel

itself.Sometimes,Iwillopenthetopofmyumbrellatoletinthesun.(WhyIam

usingmyumbrellawhenitissunnyoutsideisbeyondme!)

InSeattle,therearehundredsofthousandsoftheseumbrellasinallkindsofcolors.

Mostpeoplecallthemcars.

實(shí)現(xiàn)方法:

1、使用委托分離接口

2、使用多重繼承分離接口

五、合成/聚合復(fù)用原則(CARP)

合成/聚合復(fù)用原則(Composite/AggregateReusePrinciple或CARP)經(jīng)常又叫做合成復(fù)

用原則(CompositeReusePrinciple或CRP),就是在一個(gè)新的對(duì)象里面使用一些已有的對(duì)

象,使之成為新對(duì)象的一部分;新對(duì)象通過(guò)向這些對(duì)象的委派達(dá)到復(fù)用已有功能的目的。

簡(jiǎn)而言之,要盡量使用合成/聚合,盡量不要使用繼承。

oDesigntointerfaces.

oFavorcompositionoverinheritance.

oFindwhatvariesandencapsulateit.

(摘自:DesignPatternsExplained)

區(qū)分”Has-A”與“Is-A”

“Is-A”是嚴(yán)格的分類學(xué)意義上定義,意思是一個(gè)類是另一個(gè)類的“一種“。而"Has-A"則不同,它

表示某一個(gè)角色具有某一項(xiàng)責(zé)任。

導(dǎo)致錯(cuò)誤的使用繼承而不是合成/聚合的個(gè)常見(jiàn)的原因是錯(cuò)誤的把“Has-A"當(dāng)作"Is-A”。

例如:

實(shí)際上,雇員、經(jīng)理、學(xué)生描述的是一種角色,比如一個(gè)人是"經(jīng)理"必然是"雇員",另外一個(gè)人

可能是"學(xué)生雇員",在上面的設(shè)計(jì)中,一個(gè)人無(wú)法同時(shí)擁有多個(gè)角色,是"雇員"就不能再是"學(xué)

生"了,這顯然是不合理的。

錯(cuò)誤源于把"角色"的等級(jí)結(jié)構(gòu)與"人"的等級(jí)結(jié)構(gòu)混淆起來(lái),誤把"Has-A”當(dāng)作"Is-A"。解決辦法:

六、迪米特法則(LoD)

迪米特法則(LawofDemeter或簡(jiǎn)寫LoD)又叫最少知識(shí)原則(LeastKnowledgePrinciple

或簡(jiǎn)寫為L(zhǎng)KP),也就是說(shuō),一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其它對(duì)象有盡可能少的了解。

其它表述:

只與你直接的朋友們通信

不要跟"陌生人”說(shuō)話

每一個(gè)軟件單位對(duì)其它的單位都只有最少的知識(shí),而且局限于那些與本單位密切相關(guān)的軟件單

位。

迪米特法則與設(shè)計(jì)模式

Facade模式、Mediator模式

使民無(wú)知

《老子》第三章曰:"是以圣人之治,虛其心,實(shí)其腹,弱其志,常使民無(wú)知無(wú)欲。"使被"統(tǒng)治"

的對(duì)象"愚昧"化,處于"無(wú)知"的狀態(tài),可以使‘統(tǒng)治"的成本降低。

所謂“最少知識(shí)"原則,實(shí)際上便是老子的"使民無(wú)知"的統(tǒng)治之術(shù)。

不相往來(lái)

《老子》云:"小國(guó)寡民…鄰國(guó)相望,雞犬之聲相聞,民至老死,不相往來(lái)。”將被統(tǒng)治的對(duì)象

隔離開(kāi)來(lái),使它們沒(méi)有直接的通信,可以達(dá)到分化瓦解,繼而分而治之的效果。迪米特法則與老

子的"小國(guó)寡民"的統(tǒng)治之術(shù)不謀而合。

C#設(shè)計(jì)模式(4)—SimpieFactoryPattern

工廠模式專門負(fù)責(zé)將大量有共同接口的類實(shí)例化。工廠模式可以動(dòng)態(tài)決定將明1,一個(gè)類實(shí)例化,不

必事先知道每次要實(shí)例化哪一個(gè)類。工廠模式有以下幾種形態(tài):

?簡(jiǎn)單工廠(SimpleFactory)模式

?工廠方法(FactoryMethod)模式

?抽象工廠(AbstractFactory)模式

一、簡(jiǎn)單工廠(SimpleFactory)模式

SimpleFactory模式根據(jù)提供給它的數(shù)據(jù),返回幾個(gè)可能類中的?個(gè)類的實(shí)例。通常它返回的

類都有一個(gè)公共的父類和公共的方法。

SimpleFactory模式實(shí)際上不是GoF23個(gè)設(shè)計(jì)模式中的一員。

二、SimpieFactory模式角色與結(jié)構(gòu):

Create

工廠類角色Creator(LightSimpleFactory):工廠類在客戶端的直接控制下(Create方法)

創(chuàng)建產(chǎn)品對(duì)象。

抽象產(chǎn)品角色Product(Light):定義簡(jiǎn)單工廠創(chuàng)建的對(duì)象的父類或它們共同擁有的接口??梢?/p>

是一個(gè)類、抽象類或接口。

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

三、程序舉例:

usingSystem;

publicabstractclassLight

日叫

publicabstractvoidTurnOn();

publicabstractvoidTurnOff();

I

publicclassBulbLight:Light

日叫

publicoverridevoidTurnOn()

白由(

Console.WriteLine("BulbLightisTurnedon");

卜)

I

publicoverridevoidTurnOff()

。由(

Console.WriteLine("BulbLightisTurnedoff");

卜)

publicclassTubeLight:Light

日叫

publicoverridevoidTurnOn()

白白(

Console.WriteLine("TubeLightisTurnedon");

卜)

I

publicoverridevoidTurnOff()

的{

Console.WriteLine("TubeLightisTurnedoff");

卜)

4

publicclassLightSimpleFactory

日叫

publicLightCreate(stringLightType)

自由(

Iif(LightType=="Bulb")

returnnewBulbLight();

Ielseif(LightType=="Tube")

returnnewTubeLight();

else

returnnull;

卜}

4

publicclassClient

日叫

publicstaticvoidMain()

白由{

LightSimpleFactoryIsf=newLightSimpleFactory();

I

ILightI=lsf.Create(,'BulbM);

LTurnOn();

ILTurnOff();

I

Console.WriteLine(M");

I=lsf.Create("Tube");

LTurnOn();

LTurnOff();

L}

四、SimpieFactory模式演化

SimpleFactory模式演化(一)

除了上面的用法外,在有些情況下SimpleFactory可以由抽象產(chǎn)品角色扮演,一個(gè)抽象產(chǎn)品類

同時(shí)是子類的工廠。

Create

程序舉例:

usingSystem;

publicclassLight

日出{

publicvirtualvoidTurnOn()

由由(

卜)

I

publicvirtualvoidTurnOff()

白由(

卜)

I

publicstaticLightCreate(stringLightType)

白由(

Iif(LightType=="Bulb")

IreturnnewBulbLight();

Ielseif(LightType=="Tube")

returnnewTubeLight();

else

returnnull;

卜)

L}

publicclassBulbLight:Light

日研

publicoverridevoidTurnOn()

的{

Console.WriteLine("BulbLightisTurnedon");

卜)

I

publicoverridevoidTurnOff()

由由(

Console.WriteLine("BulbLightisTurnedoff");

卜)

publicclassTubeLight:Light

日典

publicoverridevoidTurnOn()

中由{

Console.WriteLine("TubeLightisTurnedon");

卜)

I

publicoverridevoidTurnOff()

白由(

Console.WriteLine("TubeLightisTurnedoff");

卜)

publicclassClient

日叫

publicstaticvoidMain()

白由(

LightI=Light.Create("Bulb");

LTurnOn();

ILTurnOff();

I

Console.WriteLine("

I

I=Light.Create("Tube");

LTurnOn();

ILTurnOff();

卜)

L)

SimpleFactory模式演化(二)

三個(gè)角色全部合并:

1」加

11untOnij

rumO愕)

,■(I:Liizhi

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

五、優(yōu)點(diǎn)與缺點(diǎn):

優(yōu)點(diǎn):

工廠類含有必要的判斷邏輯,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類的實(shí)例,客戶端可以免除直

接創(chuàng)建產(chǎn)品對(duì)象的責(zé)任,而僅僅"消費(fèi)”產(chǎn)品。簡(jiǎn)單工廠模式通過(guò)這種做法實(shí)現(xiàn)了對(duì)責(zé)任的分割。

缺點(diǎn):

當(dāng)產(chǎn)品有復(fù)雜的多層等級(jí)結(jié)構(gòu)時(shí),工廠類只有自己,以不變應(yīng)萬(wàn)變,就是模式的缺點(diǎn)。因?yàn)楣S

類集中了所有產(chǎn)品創(chuàng)建邏輯,一旦不能正常工作,整個(gè)系統(tǒng)都要受到影響。

同時(shí),系統(tǒng)擴(kuò)展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯,有可能造成工廠邏輯過(guò)于復(fù)雜。

另外,簡(jiǎn)單工廠模式通常使用靜態(tài)工廠方法,這使得無(wú)法由子類繼承,造成工廠角色無(wú)法形成基

于繼承的等級(jí)結(jié)構(gòu)。

C#設(shè)計(jì)模式(5)—FactoryMethodPattern

一、工廠方法(FactoryMethod)模式

工廠方法(FactoryMethod)模式是類的創(chuàng)建模式,其用意是定義?個(gè)創(chuàng)建產(chǎn)品對(duì)象的工廠接

口,將實(shí)際創(chuàng)建工作推遲到子類中。

工廠方法模式是簡(jiǎn)單工廠模式的進(jìn)一步抽象和推廣。由于使用了多態(tài)性,工廠方法模式保持了簡(jiǎn)

單工廠模式的優(yōu)點(diǎn),而且克服了它的缺點(diǎn)。

在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建工作交給子類去做。

這個(gè)核心類僅僅負(fù)責(zé)給出具體工廠必須實(shí)現(xiàn)的接口,而不接觸哪一個(gè)產(chǎn)品類被實(shí)例化這種細(xì)節(jié)。

這使得工廠方法模式可以允許系統(tǒng)在不修改工廠角色的情況卜引進(jìn)新產(chǎn)品。

在FactoryMethod模式中,工廠類與產(chǎn)品類往往具有平行的等級(jí)結(jié)構(gòu),它們之間一一對(duì)應(yīng)。

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

抽象工廠(Creator)角色:是工廠方法模式的核心,與應(yīng)用程序無(wú)關(guān)。任何在模式中創(chuàng)建的對(duì)

象的工廠類必須實(shí)現(xiàn)這個(gè)接口。

具體工廠(ConcreteCreator)角色:這是實(shí)現(xiàn)抽象工廠接口的具體工廠類,包含與應(yīng)用程序

密切相關(guān)的邏輯,并且受到應(yīng)用程序調(diào)用以創(chuàng)建產(chǎn)品對(duì)象。在上圖中有兩個(gè)這樣的角色:

BuIbCreator與TubeCreator。

抽象產(chǎn)品(Product)角色:工廠方法模式所創(chuàng)建的對(duì)象的超類型,也就是產(chǎn)品對(duì)象的共同父類

或共同擁有的接口。在上圖中,這個(gè)角色是Light。

具體產(chǎn)品(ConcreteProduct)角色:這個(gè)角色實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口。某具體產(chǎn)

品有專門的具體工廠創(chuàng)建,它們之間往往一一對(duì)應(yīng)。

三、程序舉例:

usingSystem;

publicabstractclassLight

日國(guó){

publicabstractvoidTurnOn();

publicabstractvoidTurnOff();

L)

publicclassBulbLight:Light

00(

publicoverridevoidTurnOn()

由由{Console.WriteLine("BulbLightisTurnedon");}

I

publicoverridevoidTurnOff()

中中{Console.WriteLine(HBulbLightisTurnedoff");}

publicclassTubeLight:Light

日刊{

publicoverridevoidTurnOn()

中中{Console.WriteLine("TubeLightisTurnedon");}

publicoverridevoidTurnOff()

「;1{Console.WriteLine("TubeLightisTurnedoff");}

I

publicabstractclassCreator

日叫

publicabstractLightfactory();

publicclassBuIbCreator:Creator

EJ[±]{

publicoverrideLightfactory()

中中{returnnewBulbLight();}

L)

publicclassTubeCreator:Creator

□S(

publicoverrideLightfactory()

韓{returnnewTubeLight();}

publicclassClient

日叫

publicstaticvoidMain()

的{

Creatorc1=newBulbCreator();

Creatorc2=newTubeCreator();

I

Light11=c1.factory();

LightI2=c2.factory();

I

11.TurnOn();

IM.TurnOffO;

Console.WriteLine(

l2.TurnOn();

l2.TurnOff();

卜)

工廠方法的活動(dòng)序列圖

活動(dòng)過(guò)程包括:

客戶端創(chuàng)建BuIbCreator對(duì)象,客戶端持有此對(duì)象的類型是Creator,而實(shí)際類型是

BulbCreator0然后客戶端調(diào)用BuIbCreator的factory方法,之后BuIbCreator調(diào)用

BulbLight的構(gòu)造函數(shù)創(chuàng)造出產(chǎn)品BulbLight對(duì)象。

四、工廠方法模式與簡(jiǎn)單工廠模式

工廠方法模式與簡(jiǎn)單工廠模式再結(jié)構(gòu)上的不同不是很明顯。工廠方法類的核心是一個(gè)抽象工廠

類,而簡(jiǎn)單工廠模式把核心放在一個(gè)具體類上。

工廠方法模式之所以有一個(gè)別名叫多態(tài)性工廠模式是因?yàn)榫唧w工廠類都有共同的接口,或者有共

同的抽象父類。

當(dāng)系統(tǒng)擴(kuò)展需要添加新的產(chǎn)品對(duì)象時(shí),僅僅需要添加一個(gè)具體對(duì)象以及一個(gè)具體工廠對(duì)象,原有

工廠對(duì)象不需要進(jìn)行任何修改,也不需要修改客戶端,很好的符合了"開(kāi)放一封閉"原則。而簡(jiǎn)單

工廠模式在添加新產(chǎn)品對(duì)象后不得不修改工廠方法,擴(kuò)展性不好。

工廠方法模式退化后可以演變成簡(jiǎn)單工廠模式。

五、FactoryMethod模式演化

使用接口或抽象類

抽象工廠角色和抽象場(chǎng)頻角色都可以選擇由接I」或抽象類實(shí)現(xiàn)。

使用多個(gè)工廠方法

抽象工廠角色可以規(guī)定出多于一個(gè)的工廠方法,從而使具體工廠角色實(shí)現(xiàn)這些不同的工廠方法,

這些方法可以提供不同的商業(yè)邏輯,以滿足提供不同的產(chǎn)品對(duì)象的任務(wù)。

產(chǎn)品的循環(huán)使用

工廠方法總是調(diào)用產(chǎn)品類的構(gòu)造函數(shù)以創(chuàng)建個(gè)新的產(chǎn)品實(shí)例,然后將這個(gè)實(shí)例提供給客戶端。

而在實(shí)際情形中,工廠方法所做的事情可以相當(dāng)復(fù)雜。

一個(gè)常見(jiàn)的復(fù)雜邏輯就是循環(huán)使用產(chǎn)品對(duì)象。工廠對(duì)象將已經(jīng)創(chuàng)建過(guò)的產(chǎn)品登記到一個(gè)聚集中,

然后根據(jù)客戶所請(qǐng)求的產(chǎn)品狀態(tài),向聚集查詢。如果有滿足要求的產(chǎn)品對(duì)象,就直接將產(chǎn)品返回

客戶端;如果聚集中沒(méi)有這樣的產(chǎn)品對(duì)象,那么就創(chuàng)建一個(gè)新的滿足要求的產(chǎn)品對(duì)象,然后將這

個(gè)對(duì)象登記到聚集中,再返還給客戶端。"享元模式(FlyweightPattern)"就是這樣一個(gè)模式。

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

一個(gè)工廠方法模式的實(shí)現(xiàn)依賴于工廠角色和產(chǎn)品角色的多態(tài)性。在有些情況下,這個(gè)模式可以出

現(xiàn)退化。

工廠方法返回的類型應(yīng)當(dāng)是抽象類型,而不是具體類型。調(diào)用工廠方法的客戶端應(yīng)當(dāng)依賴抽象產(chǎn)

品編程,而不是具體產(chǎn)品。如果工廠僅僅返回一個(gè)具體產(chǎn)品對(duì)象,便違背了工廠方法的用意,發(fā)

生退化,這時(shí)就不再是工廠模式了。

工廠的等級(jí)結(jié)構(gòu):工廠對(duì)象應(yīng)當(dāng)有一個(gè)抽象的超類型。如果等級(jí)結(jié)構(gòu)中只有一個(gè)具體工廠類的話,

抽象工廠就可以省略,發(fā)生了退化。

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

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

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

七、另外一個(gè)例子

//FactoryMethodpattern--RealWorldexample

usingSystem;

usingSystem.Collections;

//"Product"

abstractclassPage

□S{

//"ConcreteProduct"

classSkillsPage:Page

日叫

L)

//"ConcreteProduct"

classEducationPage:Page

日日{(diào)

//"ConcreteProduct"

classExperiencePage:Page

日典

L)

//"ConcreteProduct"

classIntroductionPage:Page

日叫

4

//"ConcreteProduct"

classResultsPage:Page

00(

I

//"ConcreteProduct"

classConclusionPage:Page

日刊

L)

//"ConcreteProduct"

classSummaryPage:Page

日日{

L)

//"ConcreteProduct"

classBibliographyPage:Page

日叫

L)

//"Creator"

abstractclassDocument

日困{

I//Fields

protectedArrayListpages=newArrayList();

I

I//Constructor

publicDocument()

的{

this.CreatePages();

卜}

I

I//Properties

publicArrayListPages

白由(

白申get{returnpages;}

卜}

I

//FactoryMethod

abstractpublicvoidCreatePages();

L)

//"ConcreteCreator"

classResume:Document

日El{

//FactoryMethodimplementation

overridepublicvoidCreatePages()

中由(

pages.Add(newSkillsPage());

pages.Add(newEducationPage());

pages.Add(newExperiencePage());

卜}

L)

//"ConcreteCreator"

classReport:Document

日困{

//FactoryMethodimplementation

overridepublicvoidCreatePages()

的{

pages.Add(newlntroductionPage());

pages.Add(newResultsPage());

Ipages.Add(newConclusionPage());

pages.Add(newSummaryPage());

pages.Add(newBibliographyPage());

卜}

4

日功//<summary>

I///FactoryMethodApptest

L///</summary>

classFactoryMethodApp

日叫

publicstaticvoidMain(string[]args)

均中{

Document[]docs=newDocument[2];

I

//Note:constructorscallFactoryMethod

docs[0]=newResume();

docs[1]=newReport();

I

//Displaydocumentpages

foreach(Documentdocumentindocs)

白由(

Console.WriteLine(""+document+”");

foreach(Pagepageindocument.Pages)

Console.WriteLine("n+page);

卜}

卜}

L)

C#設(shè)計(jì)模式(6)—AbstractFactoryPattern

一、抽象工廠(AbstractFactory)模式

抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)。

為了方便引進(jìn)抽象工廠模式,引進(jìn)一個(gè)新概念:產(chǎn)品族(ProductFamily)?所謂產(chǎn)品族,是

指位于不同產(chǎn)品等級(jí)結(jié)構(gòu),功能相關(guān)聯(lián)的產(chǎn)品組成的家族。如圖:

圖中一共有四個(gè)產(chǎn)品族,分布于三個(gè)不同的產(chǎn)品等級(jí)結(jié)構(gòu)中。只要指明一個(gè)產(chǎn)品所處的產(chǎn)品族以

及它所屬的等級(jí)結(jié)構(gòu),就可以唯一的確定這個(gè)產(chǎn)品。

引進(jìn)抽象工廠模式

所謂的抽象工廠是指一個(gè)工廠等級(jí)結(jié)構(gòu)可以創(chuàng)建出分屬于不同產(chǎn)品等級(jí)結(jié)構(gòu)的一個(gè)產(chǎn)品族中的

所有對(duì)象。如果用圖來(lái)描述的話,如下圖:

具體工J

產(chǎn)品等級(jí)結(jié)構(gòu)

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

圖中描述的東西用產(chǎn)品族描述如下:

抽象工廠(AbstractFactory)

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論