C++設(shè)計(jì)模式基礎(chǔ)教程_第1頁
C++設(shè)計(jì)模式基礎(chǔ)教程_第2頁
C++設(shè)計(jì)模式基礎(chǔ)教程_第3頁
C++設(shè)計(jì)模式基礎(chǔ)教程_第4頁
C++設(shè)計(jì)模式基礎(chǔ)教程_第5頁
已閱讀5頁,還剩200頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

C/C++與設(shè)計(jì)模式根底課程

設(shè)計(jì)模式根底

1設(shè)計(jì)模式編程根底

1.1設(shè)計(jì)模式前言

模式

在一定環(huán)境中解決某一問題的方案,包括三個(gè)根本元素-問題,解決方案和環(huán)境。

大白話:在一定環(huán)境下,用固定套路解決問題。

設(shè)計(jì)模式(Designpattern)

是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)

模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無疑問,設(shè)計(jì)模

式于己于他人于系統(tǒng)都是多贏的;設(shè)計(jì)模式使代碼編制真正工程化;

設(shè)計(jì)模式是軟件工程的基石脈絡(luò),如同大廈的結(jié)構(gòu)一樣。

學(xué)習(xí)設(shè)計(jì)模式的意義

提高職業(yè)素養(yǎng),關(guān)注學(xué)員在行業(yè)內(nèi)的長期開展。

“我眼中的設(shè)計(jì)模式"

把簡單的問題復(fù)雜化(標(biāo)準(zhǔn)化),把環(huán)境中的各個(gè)局部進(jìn)行抽象、歸納、解耦合。

不是多神秘的東西,我們初學(xué)者也能學(xué)的會(huì)。要有信心。

學(xué)習(xí)設(shè)計(jì)模式的方法

對(duì)初學(xué)者:

積累案例,大于背類圖。

初級(jí)開發(fā)人員:

多思考、多梳理,歸納總結(jié);

尊重事物的認(rèn)知規(guī)律,注意事物臨界點(diǎn)的突破。不可急躁。

中級(jí)開發(fā)人員

適宜的開發(fā)環(huán)境,尋找適宜的設(shè)計(jì)模式,解決問題。

多應(yīng)用

對(duì)經(jīng)典組合設(shè)計(jì)模式的大量、自由的運(yùn)用。要不斷的追求。

設(shè)計(jì)模式的分類

GangofFour的**DesignPatterns:ElementsofResualbelSoftware"書將設(shè)計(jì)模式歸納為

三大類型,共23種。

創(chuàng)立型模式:通常和對(duì)象的創(chuàng)立有關(guān),涉及到對(duì)象實(shí)例化的方式。(共5種模式)

結(jié)構(gòu)型模式:描述的是如何組合類和對(duì)象以獲得更大的結(jié)構(gòu)。(共7種模式)

行為型模式:用來對(duì)類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)進(jìn)行描述。(共11種模式)

創(chuàng)立型模式用來處理對(duì)象的創(chuàng)立過程,主要包含以下5種設(shè)計(jì)模式:

1,工廠方法模式(FactoryMethodPattern)的用意是定義一個(gè)創(chuàng)立產(chǎn)品對(duì)象的工廠接口,

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

2,抽象工廠模式(AbstractFactoryPattern)的意圖是提供-一個(gè)創(chuàng)立一系列相關(guān)或者相互依

賴的接口,而無需指定它們具體的類。

3,建造者模式(BuilderPattern)的意圖是將一個(gè)復(fù)雜的構(gòu)建與其表示相別離,使得同樣的

構(gòu)建過程可以創(chuàng)立不同的表示。

4,原型模式(PrototypePattern)是用原型實(shí)例指定創(chuàng)立對(duì)象的種類,并且通過拷貝這些原

型創(chuàng)立新的對(duì)象。

5,單例模式(SingletonPattern)是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪

問點(diǎn)。

結(jié)構(gòu)型模式用來處理類或者對(duì)象的組合,主要包含以下7種設(shè)計(jì)模式:

6,代理模式(ProxyPattern)就是為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。

7,裝飾者模式(DecoratorPattern)動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來

說,此模式比生成子類更為靈活。

8,適配器模式(AdapterPattern)是將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。使得

原本由于接口不兼容而不能一起工作的那些類可以一起工作。

9,橋接模式(BridgePattern)是將抽象局部與實(shí)際局部別離,使它們都可以獨(dú)立的變化。

10,組合模式(CompositePattern)是將對(duì)象組合成樹形結(jié)構(gòu)以表示"局部-整體”的層次結(jié)

構(gòu)。使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

11,外觀模式(FacadePattern)是為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,此模式定義

了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。

12,享元模式(FlyweightPattern)是以共享的方式高效的支持大量的細(xì)粒度的對(duì)象。

行為型模式用來對(duì)類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)進(jìn)行描述,主要包含以下11種設(shè)計(jì)模

式:

13,模板方法模式(TemplateMethodPattern)使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重

定義該算法的某些特定步驟。

14,命令模式(CommandPattern)是將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)

求對(duì)客戶端進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可撤銷的操作。

15,責(zé)任鏈模式(ChainofResponsibilityPattern),在該模式里,很多對(duì)象由每—個(gè)對(duì)象對(duì)其

下家的引用而連接起來形成一條鏈。請(qǐng)求在這個(gè)鏈上傳遞,直到鏈上的某一個(gè)對(duì)象決定處理

此請(qǐng)求,這使得系統(tǒng)可以在不影響客戶端的情況下動(dòng)態(tài)地重新組織鏈和分配責(zé)任。

16,策略模式(StrategyPattern)就是準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來,使得它們

可以互換。

17,中介者模式(MediatorPattern)就是定義一個(gè)中介對(duì)象來封裝系列對(duì)象之間的交互。終

結(jié)者使各個(gè)對(duì)象不需要顯示的相互調(diào)用,從而使其耦合性松散,而且可以獨(dú)立的改變他們

之間的交互。

18,觀察者模式(ObserverPattern)定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀

態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。

19,備忘錄模式(MementoPattern)是在不破壞封裝的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),

并在該對(duì)象之外保存這個(gè)狀態(tài)。

20,訪問者模式(VisitorPattern)就是表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作,它使

你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

21,狀態(tài)模式(StatePattern)就是對(duì)象的行為,依賴于它所處的狀態(tài)。

22,解釋器模式(InterpreterPattern)就是描述了如何為簡單的語言定義一個(gè)語法,如何在

該語言中表示一個(gè)句子,以及如何解釋這些句子。

23,迭代器模式(IteratorPattern)是提供了一種方法順序來訪問一個(gè)聚合對(duì)象中的各個(gè)元

素,而又不需要暴露該對(duì)象的內(nèi)部表示。

1.2設(shè)計(jì)模式根本原那么

最終目的:高內(nèi)聚,低耦合

1)開放封閉原那么(OCP,OpenForExtension,ClosedForModificationPrinciple)

類的改動(dòng)是通過增加代碼進(jìn)行的,而不是修改源代碼。

2)單一職責(zé)原那么(SRP,SingleResponsibilityPrinciple)

類的職責(zé)要單一,對(duì)外只提供一種功能,而引起類變化的原因都應(yīng)該只有一個(gè)。

3)依賴倒置原那么(DIP,DependenceInversionPrinciple)

依賴于抽象(接口),不要依賴具體的實(shí)現(xiàn)(類),也就是針對(duì)接口編程。

4)接口隔離原那么(ISP,InterfaceSegegationPrinciple)

不應(yīng)該強(qiáng)迫客戶的程序依賴他們不需要的接口方法。一個(gè)接口應(yīng)該只提供一種對(duì)外功能,

不應(yīng)該把所有操作都封裝到一個(gè)接口中去。

5)里氏替換原那么(LSP,LiskovSubstitutionPrinciple)

任何抽象類出現(xiàn)的地方都可以用他的實(shí)現(xiàn)類進(jìn)行替換。實(shí)際就是虛擬機(jī)制,語言級(jí)別實(shí)

現(xiàn)面向?qū)ο蠊δ堋?/p>

6)優(yōu)先使用組合而不是繼承原那么(CARP,Composite/AggregateReusePrinciple)

如果使用繼承,會(huì)導(dǎo)致父類的任何變換都可能影響到子類的行為。

如果使用對(duì)象組合,就降低了這種依賴關(guān)系。

7)迪米特法那么(LOD,LawofDemeter)

一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象盡可能少的了解,從而降低各個(gè)對(duì)象之間的耦合,提高系統(tǒng)的

可維護(hù)性。例如在一個(gè)程序中,各個(gè)模塊之間相互調(diào)用時(shí),通常會(huì)提供一個(gè)統(tǒng)一的接口來實(shí)

現(xiàn)。這樣其他模塊不需要了解另外一個(gè)模塊的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),這樣當(dāng)一個(gè)模塊內(nèi)部的實(shí)現(xiàn)發(fā)

生改變時(shí),不會(huì)影響其他模塊的使用。(黑盒原理)

案例圖

開閉原那么案例

繁忙

的業(yè)銀行業(yè)務(wù)員

務(wù)員1.付款

2.取款儲(chǔ)戶

3.轉(zhuǎn)賬

4.申購基金

5.其他業(yè)務(wù)

負(fù)責(zé)存款負(fù)責(zé)取款負(fù)責(zé)轉(zhuǎn)賬

依賴倒轉(zhuǎn)

1)

傳統(tǒng)的過程式設(shè)計(jì)傾向于使高層次的模塊依賴于低層次的模塊,抽象層依賴

于具體的層次。

2)

邏輯

業(yè)務(wù)

高層

法那么

迪米特

生人說

1)和陌

行解耦

生人進(jìn)

人和陌

讓某

說話

生人

象陌

和抽

某人

結(jié)合

那么

轉(zhuǎn)原

賴倒

與依

3)

2創(chuàng)立型模式

2.1單例模式

2.2.1概念

單例模式是一種對(duì)象創(chuàng)立型模式,使用單例模式,可以保證為一個(gè)類只生成唯一的實(shí)例

對(duì)象。也就是說,在整個(gè)程序空間中,該類只存在一個(gè)實(shí)例對(duì)象。

GOF對(duì)單例模式的定義是:保證一個(gè)類、只有一個(gè)實(shí)例存在,同時(shí)提供能對(duì)該實(shí)例加以

訪問的全局訪問方法。

單例模式(Singleton)結(jié)構(gòu)圖

Singleton

Singleton類,定義一個(gè)GetInstance操作,允許

-instance:Singleton客戶訪問它的唯一實(shí)例Getlnstance是一個(gè)靜態(tài)

-Singleton0方法,主要負(fù)責(zé)創(chuàng)建自己的唯一實(shí)例

+GetInstance0

2.2.2為什么使用單例模式

在應(yīng)用系統(tǒng)開發(fā)中,我們常常有以下需求:

-在多個(gè)線程之間,比方初始化一次socket資源;比方servlet環(huán)境,共享同一個(gè)資源或者

操作同一個(gè)對(duì)象

-在整個(gè)程序空間使用全局變量,共享資源

-大規(guī)模系統(tǒng)中,為了性能的考慮,需要節(jié)省對(duì)象的創(chuàng)立時(shí)間等等。

因?yàn)镾ingleton模式可以保證為一個(gè)類只生成唯一的實(shí)例對(duì)象,所以這些情況,Singleton模

式就派上用場了。

2.2.3實(shí)現(xiàn)單例步驟常用步驟

a)構(gòu)造函數(shù)私有化

b)提供一個(gè)全局的靜態(tài)方法(全局訪問點(diǎn))

c)在類中定義一個(gè)靜態(tài)指針,指向本類的變量的靜態(tài)變量指針

2.2.4餓漢式單例和懶漢式單例

懶漢式

#include<iostream>

usingnamespacestd;

〃懶漢式

classSingelton

(

private:

Singelton()

(

m_singer=NULL;

m_count=0;

cout?”構(gòu)造函數(shù)Singelton...do"?endl;

)

public:

staticSingelton*getlnstance()

(

if(m_singer==NULL)〃獺漢式:1每次獲取實(shí)例都要判斷2多線程會(huì)有問題

(

m_singer=newSingelton;

}

returnm_singer;

)

staticvoidprintT()

(

cout?"m_count:"?m_count?endl;

)

private:

staticSingelton*m_singer;

staticintm_count;

);

Singelton*Singelton::m_singer=NULL;〃懶漢式并沒有創(chuàng)立單例對(duì)象

intSingelton::m_count=0;

voidmain01_l()

cout?”演示懶漢式"?endl;

Singelton*pl=Singelton::getlnstance();〃只有在使用的時(shí)候,才去創(chuàng)立對(duì)象。

Singelton*p2=Singelton::getlnstance();

if(pl!=p2)

(

cout?”不是同一個(gè)對(duì)象"?endl;

)

else

(

cout?”是同一個(gè)對(duì)象“?endl;

)

pl->printT();

p2->printT();

system("pause");

return;

llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll

〃俄漢式

classSingelton2

private:

Singelton2()

(

m__singer=NULL;

m_count=0;

cout?”構(gòu)造函數(shù)Singelton...do"?endl;

)

public:

staticSingelton2*getlnstance()

{

//if(m_singer==NULL)

//{

//m_singer=newSingelton2;

//}

returnm_singer;

)

staticvoidSingelton2::Freelnstance()

(

if(m__singer!=NULL)

(

deletem_singer;

m_singer=NULL;

m_count=0;

)

staticvoidprintT()

(

cout?"m_count:"?m_count?endl;

)

private:

staticSingelton2*m_singer;

staticintm_count;

);

Singelton2*Singelton2::m_singer=newSingelton2;〃不管你創(chuàng)立不創(chuàng)立實(shí)例,均把實(shí)例new

出來

intSingelton2::m_count=0;

voidmain()

(

cout?”演示餓漢式"?endl;

Singelton2*pl=Singelton2::getlnstance();〃只有在使用的時(shí)候,才去創(chuàng)立對(duì)象。

Singelton2*p2=Singelton2::getlnstance();

if(pl!=p2)

cout?"不是同一個(gè)對(duì)象"?endl;

)

else

(

cout?”是同一個(gè)對(duì)象“?endl;

}

pl->printT();

p2->printT();

Singelton2::Freelnstance();

Singelton2::Freelnstance();

system("pause");

2.2.5多線程下的懶漢式單例和餓漢式單例

〃:L"懶漢"模式雖然有優(yōu)點(diǎn),但是每次調(diào)用Getlnstance()靜態(tài)方法時(shí),必須判斷

//NULL==mjnstance,使程序相對(duì)開銷增大。

//2多線程中會(huì)導(dǎo)致多個(gè)實(shí)例的產(chǎn)生,從而導(dǎo)致運(yùn)行代碼不正確以及內(nèi)存的泄露。

//3提供釋放資源的函數(shù)

討論:這是因?yàn)镃++中構(gòu)造函數(shù)并不是線程平安的。

C++中的構(gòu)造函數(shù)簡單來說分兩步:

第一步:內(nèi)存分配

第二步:初始化成員變量

由于多線程的關(guān)系,可能當(dāng)我們?cè)诜峙鋬?nèi)存好了以后,還沒來得急初始化成員變量,

就進(jìn)行線程切換,另外一個(gè)線程拿到所有權(quán)后,由于內(nèi)存已經(jīng)分配了,但是變量初始化還

沒進(jìn)行,因此打印成員變量的相關(guān)值會(huì)發(fā)生不一致現(xiàn)象.

多線程下的懶漢式問題拋出:

mainINFINITE).

該函:?數(shù)作用.

告訴內(nèi)核,客待子線程部結(jié)束完畢以

'后,:才把主進(jìn)程main,給陜醒,指向

linux:pthread_create(..,緩?fù)撕痼w)2)進(jìn)程結(jié)束了

上層應(yīng)用

WaitForSingleObject

核win內(nèi)核

1次調(diào)用2次返回

2寫時(shí)復(fù)制

子進(jìn)程和父進(jìn)程在各自的進(jìn)程空間

內(nèi)返回...

進(jìn)程空間:堆棧的內(nèi)存四區(qū)

#include"stdafx.h"

#include"windows.h"

include"winbase.h"

#include<process.h>

#include"iostream"

usingnamespacestd;

classSingelton

(

private:

Singelton()

(

count++;

cout?"Singelton構(gòu)造函數(shù)begin\n"?endl;

Sleep(lOOO);

cout?"Singelton構(gòu)造函數(shù)end\n"?endl;

)

private:

〃防止拷貝構(gòu)造和賦值操作

Singelton(constSingelton&obj){;}

Singelton&operator=(constSingelton&obj){;}

public:

staticSingelton*getSingelton()

(

〃。懶漢”模式雖然有優(yōu)點(diǎn),但是每次調(diào)用Getlnstance。靜態(tài)方法時(shí),必須判斷

//NULL==m_instance,使程序相對(duì)開銷增大。

//2多線程中會(huì)導(dǎo)致多個(gè)實(shí)例的產(chǎn)生,從而導(dǎo)致運(yùn)行代碼不正確以及內(nèi)存的泄露。

//3提供釋放資源的函數(shù)

returnsingle;

)

staticSingelton*releaseSingelton()

(

if(single!=NULL)〃需要判斷

(

釋放資源\n“《endl;

deletesingle;

single=NULL;

}

returnsingle;

)

voidpirntS()〃測試函數(shù)

(

printf("Singeltonprintstestcount:%d\n",count);

)

private:

staticSingelton*single;

staticintcount;

);

//note靜態(tài)變量類外初始化

Singelton*Singelton::single=newSingelton();

intSingelton::count=0;

int_tmainTTT(intargc,_TCHAR*argv[])

(

Singelton*sl=Singelton::getSingelton();

Singelton*s2=Singelton::getSingelton();

if(si==s2)

(

cout?"ok....equal"?endl;

)

else

(

cout?,'not.equal"?endl;

}

sl->pirntS();

Singelton::releaseSingelton();

cout?"hello...."?endl;

system("pause");

return0;

)

unsignedintthreadfunc2(void*mylpAdd)

intid=GetCurrentThreadld();

printf("\nthreadfunc%dXn",id);

return1;

)

voidthreadfunc(void*mylpAdd)

(

intid=GetCurrentThreadld();

printf("\nthreadfunc%d\n",id);

Singelton::getSingelton()->pirntS();

return;

)

int_tmain(intargc,__TCHAR*argv[])

(

inti=0;

DWORDdwThreadld[201],dwThrdParam=1;

HANDLEhThread[201];

intthreadnum=3;

for(i=0;i<threadnum;i++)

(

//hThread[i]=(HANDLE)_beginthreadex(NULL,&threadfunczNULL,

0,&dwThreadld[i]);

hThread[i]=(HANDLE)_beginthread(&threadfunc,0,0);

if(hThread[i]==NULL)

printf("beginthread%derror!!!\n",i);

break;

)

)

〃等待所有的子線程都運(yùn)行完畢后,才執(zhí)行這個(gè)代碼

for(i=0;i<threadnum;i++)

(

WaitForSingleObject(hThread[i],INFINITE);

}

printf(“等待線程結(jié)束\n“);

for(i=0;i<threadnum;i++)

(

//CloseHandle(hThread[i]);

}

Singelton::releaseSingelton();

cout?"hello...."?endl;

system("pause");

return0;

}

2.2.6多線程下懶漢式單例的Double-CheckedLocking優(yōu)化

新建MFC對(duì)話框應(yīng)用程序。

方便使用臨界區(qū)類對(duì)象,同步線程

//MFCDiagram應(yīng)用程序

#include"stdafx.h"

#include”01單例優(yōu)化.h"

#include"01單例優(yōu)化Dlg.h"

#include"afxdialogex.h"

#include"iostream"

usingnamespacestd;

〃臨界區(qū)

staticCCriticalSectioncs;

//manpthread_create()

classSingleton

(

private:

Singleton()

(

TRACE("Singletonbegin\n");

Sleep(lOOO);

TRACE("Singletonend\n");

)

Singleton(constSingleton&);

Singleton&operator=(constSingleton&);

public:

staticvoidprintV()

(

TRACE("printV..\n");

)

〃請(qǐng)思考;懶漢式的Double-Check是一個(gè)經(jīng)典問題!為什么需要2次檢查“if(plnstance==

NULL)”

場景:假設(shè)有線程1、線程2、線程3,同時(shí)資源競爭。

//1)第1個(gè)、2個(gè)、3個(gè)線程執(zhí)行第一個(gè)檢查,都有可能進(jìn)入黃色區(qū)域(臨界區(qū))

〃2)假設(shè)第1個(gè)線程進(jìn)入到臨界區(qū),第2個(gè)、第3個(gè)線程需要等待

〃3)第1個(gè)線程執(zhí)行完畢,cs.unlock()后,第2個(gè)、第3個(gè)線程要競爭執(zhí)行臨界區(qū)代碼。

〃4)假假設(shè)第2個(gè)線程進(jìn)入臨界區(qū),此時(shí)第2個(gè)線程需要再次判斷if(plnstance==NULL)",

假設(shè)第一個(gè)線程已經(jīng)創(chuàng)立實(shí)例;第2個(gè)線程就不需要再次創(chuàng)立了。保證了單例;

//5)同樣道理,假設(shè)第2個(gè)線程,cs.unlock。后,第3個(gè)線程會(huì)競爭執(zhí)行臨界區(qū)代碼;此時(shí)

第3個(gè)線程需要再次判斷if(plnstance==NULL)?通過檢查發(fā)現(xiàn)實(shí)例已經(jīng)new出來,就不需

要再次創(chuàng)立;保證了單例。

staticSingleton*lnstantialize()

{

iffplnstance==NULL)//doublecheck

(

cs.Lock();〃只有當(dāng)plnstance等于null時(shí),才開始使用加鎖機(jī)制二次檢查

if(plnstance==NULL)

plnstance=newSingleton();

)

cs.Unlock();

}

returnplnstance;

)

staticSingleton*plnstance;

);

Singleton*Singleton::plnstance=0;

voidCMyOl單例優(yōu)化Dlg::OnBnClickedButtonl()

(

CCriticalSectioncs;

cs.Lock();

cs.Unlock();

//TODO:在此添加控件通知處理程序代碼

)

voidthreadfunc(void*mylpAdd)

intid=GetCurrentThreadld();

TRACE("\nthreadfunc%d\n",id);

Singleton::lnstantialize()->printV();

//Singelton::getSingelton()->pirntS();

)

voidCMyOl單例優(yōu)化Dlg::OnBnClickedButton2()

(

inti=0;

DWORDdwThreadld[201]/dwThrdParam=1;

HANDLEhThread[201];

intthreadnum=3;

for(i=0;i<threadnum;i++)

|

//hThread[i]=(HANDLE)_beginthreadex(NULL,0,&threadfunc,NULL,

0,&dwThreadld[i]);

hThread[i]=(HANDLE)_beginthread(&threadfunc,0,0);

if(hThread[i]==NULL)

(

TRACE("beginthread%derror!i);

break;

)

}

for(i=0;i<threadnum;i++)

WaitForSingleObject(hThread[i],INFINITE);

}

TRACE("等待線程結(jié)束\n");

for(i=0;i<threadnum;i++)

//CloseHandle(hThread[i]);

}

//Singelton::releaseSingelton();

TRACE("ddddd\n");

2.2.7程序并發(fā)機(jī)制擴(kuò)展閱讀

程序的并發(fā)執(zhí)行往往帶來與時(shí)間有關(guān)的錯(cuò)誤,甚至引發(fā)災(zāi)難性的后果。這需要

引入同步機(jī)制。使用多進(jìn)程與多線程時(shí),有時(shí)需要協(xié)同兩種或多種動(dòng)作,此過程就

稱同步(Synchronization引入同步機(jī)制的第一個(gè)原因是為了控制線程之間的資源

同步訪問,因?yàn)槎鄠€(gè)線程在共享資源時(shí)如果發(fā)生訪問沖突通常會(huì)帶來不正確的后果。

例如,一個(gè)線程正在更新一個(gè)結(jié)構(gòu),同時(shí)另一個(gè)線程正試圖讀取同一個(gè)結(jié)構(gòu)。結(jié)果,

我們將無法得知所讀取的數(shù)據(jù)是新的還是舊的,或者是二者的混合。第二個(gè)原因是

有時(shí)要求確保線程之間的動(dòng)作以指定的次序發(fā)生,如一個(gè)線程需要等待由另外一個(gè)

線程所引起的事件。

為了在多線程程序中解決同步問題,Windows提供了四種主要的同步對(duì)象,

每種對(duì)象相對(duì)于線程有兩種狀態(tài)一一信號(hào)狀態(tài)(signalstate)和非信號(hào)狀態(tài)(nonsignal

state)?當(dāng)相關(guān)聯(lián)的同步對(duì)象處于信號(hào)狀態(tài)時(shí),線程可以執(zhí)行(訪問共享資源),反

之必須等待。這四種同步對(duì)象是:

(1)事件對(duì)象(Event)。事件對(duì)象作為標(biāo)志在線程間傳遞信號(hào)。一個(gè)或多個(gè)線

程可等待一個(gè)事件對(duì)象,當(dāng)指定的事件發(fā)生時(shí),事件對(duì)象通知等待線程可以開始執(zhí)

行。它有兩種類型:自動(dòng)重置(auto-reset)事件和手動(dòng)重置(manual-reset)事件。

⑵臨界區(qū)(CriticalSection).臨界區(qū)對(duì)象通過提供一個(gè)進(jìn)程內(nèi)所有線程必須

共享的對(duì)象來控制線程。只有擁有那個(gè)對(duì)象的線程可以訪問保護(hù)資源。在另一個(gè)線

程可以訪問該資源之前,前一個(gè)線程必須釋放臨界區(qū)對(duì)象,以便新的線程可以索取

對(duì)象的訪問權(quán)。

(3)互斥量(MutexSemaphore)?;コ饬康墓ぷ鞣绞椒浅n愃朴谂R界區(qū),只是

互斥量不僅保護(hù)一個(gè)進(jìn)程內(nèi)為多個(gè)線程使用的共享資源,而且還可以保護(hù)系統(tǒng)中兩

個(gè)或多個(gè)進(jìn)程之間的的共享資源。

(4)信號(hào)量(Semaphore)。信號(hào)量可以允許一個(gè)或有限個(gè)線程訪問共享資源。

它是通過計(jì)數(shù)器來實(shí)現(xiàn)的,初始化時(shí)賦予計(jì)數(shù)器以可用資源數(shù),當(dāng)將信號(hào)量提供應(yīng)

一個(gè)線程時(shí),計(jì)數(shù)器的值減1,當(dāng)一個(gè)線程釋放它時(shí),計(jì)數(shù)器值加1。當(dāng)計(jì)數(shù)器值小

于等于0時(shí),相應(yīng)線程必須等待。信號(hào)量是Windows98同步系統(tǒng)的核心。從本質(zhì)上

講,互斥量是信號(hào)量的一種特殊形式。

Windows/NT還提供了另外一種Windows95沒有的同步對(duì)象:可等待定時(shí)器

(WaitableTimer)o它可以封鎖線程的執(zhí)行,直到到達(dá)某一具體時(shí)間。這可以用于

后臺(tái)任務(wù)。

同步問題是多線程編程中最復(fù)雜的問題,后面的linux系統(tǒng)編程中,還會(huì)有更深入的介紹。

2.2.8總結(jié)

在很多人印象中,單例模式可能是23個(gè)設(shè)計(jì)模式中最簡單的一個(gè)。如果不考慮多線程,的

確如此,但是一旦要在多線程中運(yùn)用,那么從我們的教程中可以了解到,它涉及到很多

譯器,多線程,C++語言標(biāo)準(zhǔn)等方面的內(nèi)容。本專題參考的資料如下:

1、C++Primer(StanleyB.Lippman),主要參考的是模板靜態(tài)變量的初始化以及實(shí)例化。

2、MSDN,有關(guān)線程同步interlocked相關(guān)的知識(shí)。

3、EffectiveC++04條款(ScottMeyers)Non-Local-Static對(duì)象初始化順序以及Meyers

單例模式的實(shí)現(xiàn)。

4、Double-CheckedLocking,Threads,CompilerOptimizations,andMore(Scott

Meyers),解釋了由于編譯器的優(yōu)化,導(dǎo)致auto_ptr.reset函數(shù)不平安,shared_ptr

有類似情況。我們防止使用reset函數(shù)。

5、C++全局和靜態(tài)變量初始化順序的研究(CSDN)。

6、四人幫的經(jīng)典之作:設(shè)計(jì)模式

7、windows核心編程(JeffreyRichter)

2.2簡單工廠模式

221什么是簡單工廠模式

簡單工廠模式屬于類的創(chuàng)立型模式,又叫做靜態(tài)工廠方法模式。通過專門定義一個(gè)類來負(fù)

責(zé)創(chuàng)立其他類的實(shí)例,被創(chuàng)立的實(shí)例通常都具有共同的父類。

2.2.2模式中包含的角色及其職責(zé)

1.工廠(Creator)角色

簡單工廠模式的核心,它負(fù)責(zé)實(shí)現(xiàn)創(chuàng)立所有實(shí)例的內(nèi)部邏輯。工廠類可以被外界直接調(diào)

用,創(chuàng)立所需的產(chǎn)品對(duì)象。

2.抽象(Product)角色

簡單工廠模式所創(chuàng)立的所有對(duì)象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。

3.具體產(chǎn)品(ConcreteProduct)角色

簡單工廠模式所創(chuàng)立的具體實(shí)例對(duì)象

〃依賴:一個(gè)類的對(duì)象當(dāng)另外一個(gè)類的函數(shù)參數(shù)或者是返回值

3簡單工廠模式的優(yōu)缺點(diǎn)

在這個(gè)模式中,工廠類是整個(gè)模式的關(guān)鍵所在。它包含必要的判斷邏輯,能夠根據(jù)外界

給定的信息,決定究竟應(yīng)該創(chuàng)立哪個(gè)具體類的對(duì)象。用戶在使用時(shí)可以直接根據(jù)工廠類去創(chuàng)

立所需的實(shí)例,而無需了解這些對(duì)象是如何創(chuàng)立以及如何組織的。有利于整個(gè)軟件體系結(jié)構(gòu)

的優(yōu)化。不難發(fā)現(xiàn),簡單工廠模式的缺點(diǎn)也正表達(dá)在其工廠類上,由于工廠類集中了所有實(shí)

例的創(chuàng)立邏輯,所以“高內(nèi)聚”方面做的并不好。另外,當(dāng)系統(tǒng)中的具體產(chǎn)品類不斷增多時(shí),

可能會(huì)出現(xiàn)要求工廠類也要做相應(yīng)的修改,擴(kuò)展性并不很好。

2.2.3案例

include"iostream"

usingnamespacestd;

〃思想:核心思想是用一個(gè)工廠,來根據(jù)輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual

函數(shù)得到不同的結(jié)果。

〃元素分析:

〃抽象產(chǎn)品類:水果類

〃具體的水果了:香蕉類、蘋果類、梨子

〃優(yōu)點(diǎn)適用于不同情況創(chuàng)立不同的類時(shí)

〃缺點(diǎn)客戶端必須要知道基類和工廠類,耦合性差增加一個(gè)產(chǎn)品,需要修改工廠類

classFruit

(

public:

virtualvoidgetFruit()=0;

protected:

private:

};

classBanana:publicFruit

(

public:

virtualvoidgetFruit()

(

cout<<"香蕉“<<endl;

}

protected:

private:

);

classPear:publicFruit

(

public:

virtualvoidgetFruit()

(

cout<<“梨子”<<endl;

)

protected:

private:

);

classFactory

(

public:

staticFruit*Create(char*name)

{

Fruit*tmp=NULL;

if(strcmpfname,"pear")==0)

(

tmp=newPear();

)

elseif(strcmpfname,"banana")==0)

(

tmp=newBanana();

)

else

(

returnNULL;

}

returntmp;

)

protected:

private:

);

voidmain41()

(

Fruit*pear=Factory::Create("pear");

if(pear==NULL)

{

cout<<"創(chuàng)立pear失敗\n”;

}

pear->getFruit();

Fruit*banana=Factory::Create("banana");

banana->getFruit();

system("pause");

2.2.4練習(xí)

主要用于創(chuàng)立對(duì)象。新添加類時(shí),不會(huì)影響以前的系統(tǒng)代碼。核心思想是用一個(gè)工廠來根據(jù)

輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual函數(shù)得到不同的結(jié)果。

GOOD:適用于不同情況創(chuàng)立不同的類時(shí)

BUG:客戶端必須要知道基類和工廠類,耦合性差

?*IT?

(工廠類與基類為關(guān)聯(lián)關(guān)系〕

#include"iostream"

usingnamespacestd;

〃需求:〃模擬四那么運(yùn)算;

〃用操作符工廠類生產(chǎn)操作符(加減乘除),進(jìn)行結(jié)果運(yùn)算

〃運(yùn)算符抽象類COperation

〃加減乘除具體的類(注意含有2個(gè)操作數(shù))

〃工廠類CCalculatorFactory

〃核心思想用一個(gè)工廠來根據(jù)輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual函數(shù)得

到不同的結(jié)果

classCOperation

public:

intfirst;

intsecond;

public:

virtualdoubleGetResult()=0;

private:

);

classAddOperation:publicCOperation

(

public:

doubleGetResult()

(

returnfirst+second;

)

private:

);

classSubOperation:publicCOperation

(

public:

doubleGetResult()

(

returnfirst-second;

)

private:

);

classCCalculatorFactory

(

public:

staticCOperation*CreateOperation(charcOperator)

(

COperation*tmp=NULL;

switch(cOperator)

(

case

tmp=newAddOperation();

break;

case,J:

tmp=newSubOperation();

break;

default:

tmp=NULL;

}

returntmp;

)

);

voidmain()

COperation*opl=CCalculatorFactory::CreateOperation('+');

opl->first=10;

opl->second=20;

cout?opl->GetResult()?endl;

COperation*op2=CCalculatorFactory::CreateOperation('-');

op2->first=10;

op2->second=20;

cout?op2->GetResult()?endl;

cout?"hello...\n";

system("pause");

}

2.3工廠模式

2.3.1概念

工廠方法模式同樣屬于類的創(chuàng)立型模式又被稱為多態(tài)工廠模式。工廠方法模式的意義是

定義一個(gè)創(chuàng)立產(chǎn)品對(duì)象的工廠接口,將實(shí)際創(chuàng)立工作推遲到子類當(dāng)中。

核心工廠類不再負(fù)責(zé)產(chǎn)品的創(chuàng)立,這樣核心類成為一個(gè)抽象工廠角色,僅負(fù)責(zé)具體工廠子類

必須實(shí)現(xiàn)的接口,這樣進(jìn)一步抽象化的好處是使得工廠方法模式可以使系統(tǒng)在不修改具體工

廠角色的情況下引進(jìn)新的產(chǎn)品。

2.3.2類圖角色和職責(zé)

抽象工廠(Creator)角色

工廠方法模式的核心,任何工廠類都必須實(shí)現(xiàn)這個(gè)接口。

具體工廠(ConcreteCreator)角色

具體工廠類是抽象工廠的一個(gè)實(shí)現(xiàn),負(fù)責(zé)實(shí)例化產(chǎn)品對(duì)象。

抽象(Product)角色

工廠方法模式所創(chuàng)立的所有對(duì)象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。

具體產(chǎn)品(ConcreteProduct)角色

工廠方法模式所創(chuàng)立的具體實(shí)例對(duì)象

工廠方法模式(FactoryMethod)結(jié)構(gòu)圖

2.3.3工廠方法模式和簡單工廠模式比擬

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

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

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

或者有共同的抽象父類。

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

象,原有工廠對(duì)象不需要進(jìn)行任何修改,也不需要修改客戶端,很好的符合了“開放一封閉”

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

模式退化后可以演變成簡單工廠模式。

“開放一封閉"通過添加代碼的方式,不是通過修改代碼的方式完成功能的增強(qiáng)。

#include"iostream"

usingnamespacestd;

classFruit

(

public:

virtualvoidsayname()

(

cout?"fruit\n";

)

);

classFruitFactory

(

public:

virtualFruit*getFruitf)

(

returnnewFruit();

)

);

〃香蕉

classBanana:publicFruit

{

public:

virtualvoidsayname()

cout?"Banana\n"?endl;

}

);

〃香蕉工廠

classBananaFactory:publicFruitFactory

(

public:

virtualFruit*getFruit()

(

returnnewBanana;

)

);

〃蘋果

classApple:publicFruit

(

public:

virtualvoidsayname()

cout?"Apple\n"?endl;

)

);

〃蘋果工廠

classAppleFactory:publicFruitFactory

(

public:

virtualFruit*getFruit()

(

returnnewApple;

}

);

voidmain()

(

FruitFactory*ff=NULL;

Fruit*fruit=NULL;

//I

ff=newBananaFactory();

fruit=ff->getFruit();

fruit->sayname();

deletefruit;

deleteff;

〃2蘋果

ff=newAppleFactoryO;

fruit=ff->getFruit();

fruit->sayname();

deletefruit;

deleteff;

cout?"hello....\n";

system("pause");

2.4抽象工廠

2.4.1概念

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

客戶端提供一個(gè)接口,使得客戶端在不必指定產(chǎn)品的具體類型的情況下,能夠創(chuàng)立多個(gè)產(chǎn)品

族的產(chǎn)品對(duì)象。

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

產(chǎn)品族

備注1:工廠模式:要么生產(chǎn)香蕉、要么生產(chǎn)蘋果、要么生產(chǎn)西紅柿;但是不能同時(shí)生產(chǎn)一

個(gè)產(chǎn)品組。抽象工廠:能同時(shí)生產(chǎn)一個(gè)產(chǎn)品族。===?抽象工廠存在原因

解釋:具體工廠在開閉原那么下,能生產(chǎn)香蕉/蘋果/梨子;(產(chǎn)品等級(jí)結(jié)構(gòu))

抽象工廠:在開閉原那么下,能生產(chǎn):南方香蕉/蘋果/梨子(產(chǎn)品族)

北方香蕉/蘋果/梨子

重要區(qū)別:

工廠模式只能生產(chǎn)一個(gè)產(chǎn)品。(要么香蕉、要么蘋果)

抽象工廠可以一下生產(chǎn)一個(gè)產(chǎn)品族(里面有很多產(chǎn)品組成)

2.4.3模式中包含的角色及其職責(zé)

1.抽象工廠(Creator)角色

抽象工廠模式的核心,包含對(duì)多個(gè)產(chǎn)品結(jié)構(gòu)的聲明,任何工廠類都必須實(shí)現(xiàn)這個(gè)接口。

2.具體工廠(ConcreteCreator)角色

具體工廠類是抽象工廠的一個(gè)實(shí)現(xiàn),負(fù)責(zé)實(shí)例化某個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象。

3.抽象(Product)角色

抽象模式所創(chuàng)立的所有對(duì)象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。

4.具體產(chǎn)品(ConcreteProduct)角色

抽象模式所創(chuàng)立的具體實(shí)例對(duì)象

抽象工廠模式(AbstractFactory)結(jié)構(gòu)圖

2.4.4案例

classFruit

(

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論