版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《大學(xué)計(jì)算機(jī)基礎(chǔ)》課件-第5章 電子表格處理軟件
- 填報(bào)志愿 合同
- 《正向間接血凝試驗(yàn)》課件
- 2025年吐魯番道路貨運(yùn)駕駛員從業(yè)資格考試題庫
- 2025年湖北貨運(yùn)從業(yè)資格證考試模擬考試題目
- 2025年長沙貨運(yùn)從業(yè)資格證考試題目和答案
- 2025年張掖駕??荚囏涍\(yùn)從業(yè)資格證模擬考試
- 2025年河源考貨運(yùn)資格證考試內(nèi)容
- 工業(yè)用地交易中介合同樣本
- 水利工程機(jī)械施工安全協(xié)議
- 脊柱外科臨床指南
- 萬千教育學(xué)前透視幼兒的戶外學(xué)習(xí)
- 《抗菌藥物知識(shí)培訓(xùn)》課件
- 2024年北京市安全員A證考試題庫附答案
- 醫(yī)療專業(yè)人員的情緒管理培訓(xùn)
- 森林法培訓(xùn)課件
- 儀器分析題庫(含答案)
- 招標(biāo)法律法規(guī)匯總
- 湖北省黃岡市2022-2023學(xué)年高一上學(xué)期元月期末數(shù)學(xué)試題(原卷版)
- 2023配電網(wǎng)線損理論計(jì)算導(dǎo)則
- 審計(jì)人員保密守則
評(píng)論
0/150
提交評(píng)論