cc與設(shè)計(jì)模式基礎(chǔ)課程講義v1.0.4_第1頁
cc與設(shè)計(jì)模式基礎(chǔ)課程講義v1.0.4_第2頁
cc與設(shè)計(jì)模式基礎(chǔ)課程講義v1.0.4_第3頁
cc與設(shè)計(jì)模式基礎(chǔ)課程講義v1.0.4_第4頁
cc與設(shè)計(jì)模式基礎(chǔ)課程講義v1.0.4_第5頁
已閱讀5頁,還剩124頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、C/C+與設(shè)計(jì)模式基礎(chǔ)課程 傳智掃地僧 設(shè)計(jì)模式基礎(chǔ)1設(shè)計(jì)模式編程基礎(chǔ)1.1設(shè)計(jì)模式前言模式 在一定環(huán)境中解決某一問題的方案,包括三個(gè)基本元素-問題,解決方案和環(huán)境。大白話:在一定環(huán)境下,用固定套路解決問題。設(shè)計(jì)模式(Design pattern) 是一套被反復(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è)的長期發(fā)展?!拔已壑械脑O(shè)計(jì)模式”把

2、簡單的問題復(fù)雜化(標(biāo)準(zhǔn)版),把環(huán)境中的各個(gè)部分進(jìn)行抽象、歸納、解耦合。不是多神秘的東西,我們初學(xué)者也能學(xué)的會(huì)。要有信心。學(xué)習(xí)設(shè)計(jì)模式的方法對初學(xué)者:積累案例,大于背類圖。初級開發(fā)人員:多思考、多梳理,歸納總結(jié);尊重事物的認(rèn)知規(guī)律,注意事物臨界點(diǎn)的突破。不可浮躁。中級開發(fā)人員合適的開發(fā)環(huán)境,尋找合適的設(shè)計(jì)模式,解決問題。多應(yīng)用對經(jīng)典組合設(shè)計(jì)模式的大量、自由的運(yùn)用。要不斷的追求。設(shè)計(jì)模式的分類Gang of Four的“Design Patterns: Elements of Resualbel Software”書將設(shè)計(jì)模式歸納為三大類型,共23種。 創(chuàng)建型模式 : 通常和對象的創(chuàng)建有關(guān),涉及到

3、對象實(shí)例化的方式。(共5種模式) 結(jié)構(gòu)型模式: 描述的是如何組合類和對象以獲得更大的結(jié)構(gòu)。(共7種模式)行為型模式: 用來對類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)進(jìn)行描述。(共11種模式)創(chuàng)建型模式用來處理對象的創(chuàng)建過程,主要包含以下5種設(shè)計(jì)模式: 1,工廠方法模式(Factory Method Pattern)的用意是定義一個(gè)創(chuàng)建產(chǎn)品對象的工廠接口,將實(shí)際創(chuàng)建工作推遲到子類中。2,抽象工廠模式(Abstract Factory Pattern)的意圖是提供一個(gè)創(chuàng)建一系列相關(guān)或者相互依賴的接口,而無需指定它們具體的類。3,建造者模式(Builder&#

4、160;Pattern)的意圖是將一個(gè)復(fù)雜的構(gòu)建與其表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。4,原型模式(Prototype Pattern)是用原型實(shí)例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。5,單例模式(Singleton Pattern)是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。 結(jié)構(gòu)型模式用來處理類或者對象的組合,主要包含以下7種設(shè)計(jì)模式:6,代理模式(Proxy Pattern)就是為其他對象提供一種代理以控制對這個(gè)對象的訪問。7,裝飾者模式(Decorator Pattern)動(dòng)態(tài)的給一個(gè)對象添

5、加一些額外的職責(zé)。就增加功能來說,此模式比生成子類更為靈活。 8,適配器模式(Adapter Pattern)是將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。  9,橋接模式(Bridge Pattern)是將抽象部分與實(shí)際部分分離,使它們都可以獨(dú)立的變化。10,組合模式(Composite Pattern)是將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。使得用戶對單個(gè)對象和組合對象的使用具有一致性。11,外觀模式(Facade Pattern)是為子系統(tǒng)中的一組

6、接口提供一個(gè)一致的界面,此模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。12,享元模式(Flyweight Pattern)是以共享的方式高效的支持大量的細(xì)粒度的對象。 行為型模式用來對類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)進(jìn)行描述,主要包含以下11種設(shè)計(jì)模式:13,模板方法模式(Template Method Pattern)使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。 14,命令模式(Command Pattern)是將一個(gè)請求封裝為一個(gè)對象,從而使你可用不同的請求對客戶端進(jìn)行參數(shù)化;對請求排隊(duì)或記錄請求

7、日志,以及支持可撤銷的操作。15,責(zé)任鏈模式(Chain of Responsibility Pattern),在該模式里,很多對象由每一個(gè)對象對其下家的引用而連接起來形成一條鏈。請求在這個(gè)鏈上傳遞,直到鏈上的某一個(gè)對象決定處理此請求,這使得系統(tǒng)可以在不影響客戶端的情況下動(dòng)態(tài)地重新組織鏈和分配責(zé)任。  16,策略模式(Strategy Pattern)就是準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來,使得它們可以互換。17,中介者模式(Mediator Pattern)就是定義一個(gè)中介對象來封裝系列對象之間的交互。終結(jié)者使各個(gè)對象不

8、需要顯示的相互調(diào)用 ,從而使其耦合性松散,而且可以獨(dú)立的改變他們之間的交互。18,觀察者模式(Observer Pattern)定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知并被自動(dòng)更新。19,備忘錄模式(Memento Pattern)是在不破壞封裝的前提下,捕獲一個(gè)對象的部狀態(tài),并在該對象之外保存這個(gè)狀態(tài)。20,訪問者模式(Visitor Pattern)就是表示一個(gè)作用于某對象結(jié)構(gòu)中的各元素的操作,它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。21,狀態(tài)模式(State Pat

9、tern)就是對象的行為,依賴于它所處的狀態(tài)。22,解釋器模式(Interpreter Pattern)就是描述了如何為簡單的語言定義一個(gè)語法,如何在該語言中表示一個(gè)句子,以及如何解釋這些句子。 23,迭代器模式(Iterator Pattern)是提供了一種方法順序來訪問一個(gè)聚合對象中的各個(gè)元素,而又不需要暴露該對象的部表示。1.2設(shè)計(jì)模式基本原則最終目的:高聚,低耦合1) 開放封閉原則 (OCP,Open For Extension, Closed For Modification Principle)類的改動(dòng)是通過增加代碼進(jìn)行的,而不是修改源代碼。2) 單一

10、職責(zé)原則 (SRP,Single Responsibility Principle)類的職責(zé)要單一,對外只提供一種功能,而引起類變化的原因都應(yīng)該只有一個(gè)。3) 依賴倒置原則 (DIP,Dependence Inversion Principle)依賴于抽象(接口),不要依賴具體的實(shí)現(xiàn)(類),也就是針對接口編程。4) 接口隔離原則 (ISP,Interface Segegation Principle)不應(yīng)該強(qiáng)迫客戶的程序依賴他們不需要的接口方法。一個(gè)接口應(yīng)該只提供一種對外功能,不應(yīng)該把所有操作都封裝到一個(gè)接口中去。5) 里氏替換原則 (LSP, Liskov Substitution Prin

11、ciple) 任何抽象類出現(xiàn)的地方都可以用他的實(shí)現(xiàn)類進(jìn)行替換。實(shí)際就是虛擬機(jī)制,語言級別實(shí)現(xiàn)面向?qū)ο蠊δ堋?) 優(yōu)先使用組合而不是繼承原則(CARP,Composite/Aggregate Reuse Principle)如果使用繼承,會(huì)導(dǎo)致父類的任何變換都可能影響到子類的行為。如果使用對象組合,就降低了這種依賴關(guān)系。7) 迪米特法則(LOD,Law of Demeter)一個(gè)對象應(yīng)當(dāng)對其他對象盡可能少的了解,從而降低各個(gè)對象之間的耦合,提高系統(tǒng)的可維護(hù)性。例如在一個(gè)程序中,各個(gè)模塊之間相互調(diào)用時(shí),通常會(huì)提供一個(gè)統(tǒng)一的接口來實(shí)現(xiàn)。這樣其他模塊不需要了解另外一個(gè)模塊的部實(shí)現(xiàn)細(xì)節(jié),這樣當(dāng)一個(gè)模塊部

12、的實(shí)現(xiàn)發(fā)生改變時(shí),不會(huì)影響其他模塊的使用。(黑盒原理)案例圖開閉原則案例依賴倒轉(zhuǎn)1)2)迪米特法則 1)和陌生人說話2)不和陌生人說話3) 與依賴倒轉(zhuǎn)原則結(jié)合 某人和 抽象陌生人說話 讓某人和陌生人進(jìn)行解耦合2創(chuàng)建型模式2.1單例模式 2.2.1概念單例模式是一種對象創(chuàng)建型模式,使用單例模式,可以保證為一個(gè)類只生成唯一的實(shí)例對象。也就是說,在整個(gè)程序空間中,該類只存在一個(gè)實(shí)例對象。 GoF對單例模式的定義是:保證一個(gè)類、只有一個(gè)實(shí)例存在,同時(shí)提供能對該實(shí)例加以訪問的全局訪問方法。2.2.2為什么使用單例模式在應(yīng)用系統(tǒng)開發(fā)中,我們常常有以下需求:- 在多個(gè)線程之間,比如初始化一次socket資源

13、;比如servlet環(huán)境,共享同一個(gè)資源或者操作同一個(gè)對象- 在整個(gè)程序空間使用全局變量,共享資源- 大規(guī)模系統(tǒng)中,為了性能的考慮,需要節(jié)省對象的創(chuàng)建時(shí)間等等。因?yàn)镾ingleton模式可以保證為一個(gè)類只生成唯一的實(shí)例對象,所以這些情況,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>using namespace std;/懶漢式class Singeltonpr

14、ivate:Singelton()m_singer = NULL;m_count = 0;cout << "構(gòu)造函數(shù)Singelton . do" << endl;public:static Singelton *getInstance()if (m_singer = NULL ) /懶漢式:1 每次獲取實(shí)例都要判斷 2 多線程會(huì)有問題m_singer = new Singelton;return m_singer;static void printT()cout << "m_count: " << m_c

15、ount << endl;private:static Singelton *m_singer;static int m_count;Singelton *Singelton:m_singer = NULL; /懶漢式 并沒有創(chuàng)建單例對象int Singelton:m_count = 0;void main01_1()cout << "演示 懶漢式" << endl;Singelton *p1 = Singelton:getInstance(); /只有在使用的時(shí)候,才去創(chuàng)建對象。Singelton *p2 = Singelton:get

16、Instance();if (p1 != p2)cout << "不是同一個(gè)對象" << endl;elsecout << "是同一個(gè)對象" << endl;p1->printT();p2->printT();system("pause");return ;/俄漢式class Singelton2private:Singelton2()m_singer = NULL;m_count = 0;cout << "構(gòu)造函數(shù)Singelton . do"

17、; << endl;public:static Singelton2 *getInstance()/ if (m_singer = NULL )/ / m_singer = new Singelton2;/ return m_singer;static void Singelton2:FreeInstance()if (m_singer != NULL)delete m_singer;m_singer = NULL;m_count = 0;static void printT()cout << "m_count: " << m_count

18、 << endl;private:static Singelton2 *m_singer;static int m_count;Singelton2 *Singelton2:m_singer = new Singelton2; /不管你創(chuàng)建不創(chuàng)建實(shí)例,均把實(shí)例new出來int Singelton2:m_count = 0;void main()cout << "演示 餓漢式" << endl;Singelton2 *p1 = Singelton2:getInstance(); /只有在使用的時(shí)候,才去創(chuàng)建對象。Singelton2 *p2

19、 = Singelton2:getInstance();if (p1 != p2)cout << "不是同一個(gè)對象" << endl;elsecout << "是同一個(gè)對象" << endl;p1->printT();p2->printT();Singelton2:FreeInstance();Singelton2:FreeInstance();system("pause");2.2.5多線程下的懶漢式單例和餓漢式單例 /1"懶漢"模式雖然有優(yōu)點(diǎn),但是每次

20、調(diào)用GetInstance()靜態(tài)方法時(shí),必須判斷/NULL = m_instance,使程序相對開銷增大。/2多線程中會(huì)導(dǎo)致多個(gè)實(shí)例的產(chǎn)生,從而導(dǎo)致運(yùn)行代碼不正確以及存的泄露。/3提供釋放資源的函數(shù)討論: 這是因?yàn)镃+中構(gòu)造函數(shù)并不是線程安全的。 C+中的構(gòu)造函數(shù)簡單來說分兩步: 第一步:存分配 第二步:初始化成員變量 由于多線程的關(guān)系,可能當(dāng)我們在分配存好了以后,還沒來得急初始化成員變量,就進(jìn)行線程切換,另外一個(gè)線程拿到所有權(quán)后,由于存已經(jīng)分配了,但是變量初始化還 沒進(jìn)行,因此打印成員變量的相關(guān)值會(huì)發(fā)生不一致現(xiàn)象。多線程下的懶漢式問題拋出:#include "stdafx.h&q

21、uot;#include "windows.h"#include "winbase.h"#include <process.h>#include "iostream"using namespace std;class Singeltonprivate:Singelton()count +;cout<<"Singelton構(gòu)造函數(shù)beginn"<<endl;Sleep(1000);cout<<"Singelton構(gòu)造函數(shù)endn"<<en

22、dl;private:/防止拷貝構(gòu)造和賦值操作Singelton(const Singelton &obj) ;Singelton& operator=(const Singelton &obj) ;public:static Singelton *getSingelton()/1"懶漢"模式雖然有優(yōu)點(diǎn),但是每次調(diào)用GetInstance()靜態(tài)方法時(shí),必須判斷/NULL = m_instance,使程序相對開銷增大。/2多線程中會(huì)導(dǎo)致多個(gè)實(shí)例的產(chǎn)生,從而導(dǎo)致運(yùn)行代碼不正確以及存的泄露。/3提供釋放資源的函數(shù)return single;static

23、Singelton *releaseSingelton()if (single != NULL) /需要判斷cout<<"釋放資源n"<<endl;delete single;single = NULL;return single;void pirntS() /測試函數(shù)printf("Singelton printS test count:%d n", count);private:static Singelton *single;static int count;/note 靜態(tài)變量類外初始化Singelton *Singelt

24、on:single = new Singelton();int Singelton:count = 0;int _tmainTTT(int argc, _TCHAR* argv)Singelton *s1 = Singelton:getSingelton();Singelton *s2 = Singelton:getSingelton();if (s1 = s2)cout<<"ok.equal"<<endl;elsecout<<"not.equal"<<endl;s1->pirntS();Singel

25、ton:releaseSingelton();cout <<"hello."<<endl;system("pause");return 0;unsigned int threadfunc2(void *myIpAdd)int id = GetCurrentThreadId();printf("n threadfunc%d n", id);return 1;void threadfunc(void *myIpAdd)int id = GetCurrentThreadId();printf("n thre

26、adfunc%d n", id); Singelton:getSingelton()->pirntS();return ; int _tmain(int argc, _TCHAR* argv)int i = 0; DWORD dwThreadId201, dwThrdParam = 1;HANDLE hThread201; int threadnum = 3;for (i=0; i<threadnum; i+)/hThreadi = (HANDLE)_beginthreadex( NULL, 0, &threadfunc, NULL, 0,&dwThrea

27、dIdi );hThreadi = (HANDLE)_beginthread(&threadfunc, 0 , 0 );if (hThreadi = NULL)printf("begin thread %d error!n", i);break;for (i=0; i<threadnum; i+)WaitForSingleObject( hThreadi, INFINITE );printf("等待線程結(jié)束n");for (i=0; i<threadnum; i+)/CloseHandle( hThreadi );Singelton:

28、releaseSingelton();cout <<"hello."<<endl;system("pause");return 0;2.2.6多線程下懶漢式單例的Double-Checked Locking優(yōu)化新建MFC對話框應(yīng)用程序。方便使用臨界區(qū)類對象,同步線程/ MFC Diagram 應(yīng)用程序#include "stdafx.h"#include "01單例優(yōu)化.h"#include "01單例優(yōu)化Dlg.h"#include "afxdialogex.

29、h"#include "iostream"using namespace std;/臨界區(qū)static CCriticalSection cs;class Singletonprivate:Singleton()TRACE("Singleton beginn");Sleep(1000);TRACE("Singleton endn");Singleton(const Singleton &);Singleton& operator = (const Singleton &);public:static

30、void printV()TRACE("printV.n");/請思考;懶漢式的Double-Check是一個(gè)經(jīng)典問題!為什么需要2次檢查 “if(pInstance = NULL)”場景:假設(shè)有線程1、線程2、線程3,同時(shí)資源競爭。/1)第1個(gè)、2個(gè)、3個(gè)線程執(zhí)行第一個(gè)檢查,都有可能進(jìn)入黃色區(qū)域(臨界區(qū))/2)若第1個(gè)線程進(jìn)入到臨界區(qū),第2個(gè)、第3個(gè)線程需要等待/3)第1個(gè)線程執(zhí)行完畢,cs.unlock()后,第2個(gè)、第3個(gè)線程要競爭執(zhí)行臨界區(qū)代碼。/4)假若第2個(gè)線程進(jìn)入臨界區(qū),此時(shí)第2個(gè)線程需要再次判斷 if(pInstance = NULL)”,若第一個(gè)線程已經(jīng)創(chuàng)

31、建實(shí)例;第2個(gè)線程就不需要再次創(chuàng)建了。保證了單例;/5)同樣道理,若第2個(gè)線程,cs.unlock()后,第3個(gè)線程會(huì)競爭執(zhí)行臨界區(qū)代碼;此時(shí)第3個(gè)線程需要再次判斷 if(pInstance = NULL)。通過檢查發(fā)現(xiàn)實(shí)例已經(jīng)new出來,就不需要再次創(chuàng)建;保證了單例。static Singleton *Instantialize()if(pInstance = NULL) /double check cs.Lock(); /只有當(dāng)pInstance等于null時(shí),才開始使用加鎖機(jī)制 二次檢查if(pInstance = NULL)pInstance = new Singleton();cs.

32、Unlock();return pInstance;static Singleton *pInstance;Singleton* Singleton:pInstance = 0;void CMy01單例優(yōu)化Dlg:OnBnClickedButton1()CCriticalSection cs;cs.Lock();cs.Unlock();/ TODO: 在此添加控件通知處理程序代碼void threadfunc(void *myIpAdd)int id = GetCurrentThreadId();TRACE("n threadfunc%d n", id);Singleton

33、:Instantialize()->printV();/Singelton:getSingelton()->pirntS();void CMy01單例優(yōu)化Dlg:OnBnClickedButton2()int i = 0; DWORD dwThreadId201, dwThrdParam = 1;HANDLE hThread201; int threadnum = 3;for (i=0; i<threadnum; i+)/hThreadi = (HANDLE)_beginthreadex( NULL, 0, &threadfunc, NULL, 0,&dwTh

34、readIdi );hThreadi = (HANDLE)_beginthread(&threadfunc, 0 , 0 );if (hThreadi = NULL)TRACE("begin thread %d error!n", i);break;for (i=0; i<threadnum; i+)WaitForSingleObject( hThreadi, INFINITE );TRACE("等待線程結(jié)束n");for (i=0; i<threadnum; i+)/CloseHandle( hThreadi );/Singelto

35、n:releaseSingelton();TRACE("dddddn");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)作

36、以指定的次序發(fā)生,如一個(gè)線程需要等待由另外一個(gè)線程所引起的事件。為了在多線程程序中解決同步問題,Windows提供了四種主要的同步對象,每種對象相對于線程有兩種狀態(tài)信號狀態(tài)(signal state)和非信號狀態(tài)(nonsignalstate)。當(dāng)相關(guān)聯(lián)的同步對象處于信號狀態(tài)時(shí),線程可以執(zhí)行(訪問共享資源),反之必須等待。這四種同步對象是:(1)事件對象(Event)。事件對象作為標(biāo)志在線程間傳遞信號。一個(gè)或多個(gè)線程可等待一個(gè)事件對象,當(dāng)指定的事件發(fā)生時(shí),事件對象通知等待線程可以開始執(zhí)行。它有兩種類型:自動(dòng)重置(auto-reset)事件和手動(dòng)重置(manual-reset)事件。(2)臨界區(qū)

37、(Critical Section)。臨界區(qū)對象通過提供一個(gè)進(jìn)程所有線程必須共享的對象來控制線程。只有擁有那個(gè)對象的線程可以訪問保護(hù)資源。在另一個(gè)線程可以訪問該資源之前,前一個(gè)線程必須釋放臨界區(qū)對象,以便新的線程可以索取對象的訪問權(quán)。(3)互斥量(Mutex Semaphore)?;コ饬康墓ぷ鞣绞椒浅n愃朴谂R界區(qū),只是互斥量不僅保護(hù)一個(gè)進(jìn)程為多個(gè)線程使用的共享資源,而且還可以保護(hù)系統(tǒng)中兩個(gè)或多個(gè)進(jìn)程之間的的共享資源。(4)信號量(Semaphore)。信號量可以允許一個(gè)或有限個(gè)線程訪問共享資源。它是通過計(jì)數(shù)器來實(shí)現(xiàn)的,初始化時(shí)賦予計(jì)數(shù)器以可用資源數(shù),當(dāng)將信號量提供給一個(gè)線程時(shí),計(jì)數(shù)器的值減1,

38、當(dāng)一個(gè)線程釋放它時(shí),計(jì)數(shù)器值加1。當(dāng)計(jì)數(shù)器值小于等于0時(shí),相應(yīng)線程必須等待。信號量是Windows98同步系統(tǒng)的核心。從本質(zhì)上講,互斥量是信號量的一種特殊形式。Windows/NT還提供了另外一種Windows95沒有的同步對象:可等待定時(shí)器(Waitable Timer)。它可以封鎖線程的執(zhí)行,直到到達(dá)某一具體時(shí)間。這可以用于后臺任務(wù)。同步問題是多線程編程中最復(fù)雜的問題,后面的linux系統(tǒng)編程中,還會(huì)有更深入的介紹。2.2.8總結(jié) 在很多人印象中,單例模式可能是23個(gè)設(shè)計(jì)模式中最簡單的一個(gè)。如果不考慮多線程,的 確如此,但是一旦要在多線程中運(yùn)用,那么從我們的教程中可以了解到,它涉及到很多編

39、 譯器,多線程,C+語言標(biāo)準(zhǔn)等方面的容。本專題參考的資料如下: 1、C+ Primer (Stanley B.Lippman),主要參考的是模板靜態(tài)變量的初始化以及實(shí)例化。 2、 MSDN,有關(guān)線程同步interlocked相關(guān)的知識。 3、Effective C+ 04條款(Scott Meyers) Non-Local-Static對象初始化順序以及Meyers 單例模式的實(shí)現(xiàn)。 4、Double-Checked Locking,Threads,Compiler Optimizations,and More(Scott Meyers),解釋了由于編譯器的優(yōu)化,導(dǎo)致auto_ptr.rese

40、t函數(shù)不安全,shared_ptr 有類似情況。我們避免使用reset函數(shù)。 5、C+全局和靜態(tài)變量初始化順序的研究(CSDN)。 6、四人幫的經(jīng)典之作:設(shè)計(jì)模式 7、windows 核心編程(Jeffrey Richter) 2.2簡單工廠模式2.2.1什么是簡單工廠模式 簡單工廠模式屬于類的創(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í)例的部邏輯。工廠類可以被外界直接調(diào)用,創(chuàng)建所需的產(chǎn)品對象。2.抽象(Product)角色

41、簡單工廠模式所創(chuàng)建的所有對象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。3.具體產(chǎn)品(Concrete Product)角色簡單工廠模式所創(chuàng)建的具體實(shí)例對象/依賴: 一個(gè)類的對象 當(dāng)另外一個(gè)類的函數(shù)參數(shù) 或者是 返回值3簡單工廠模式的優(yōu)缺點(diǎn) 在這個(gè)模式中,工廠類是整個(gè)模式的關(guān)鍵所在。它包含必要的判斷邏輯,能夠根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類的對象。用戶在使用時(shí)可以直接根據(jù)工廠類去創(chuàng)建所需的實(shí)例,而無需了解這些對象是如何創(chuàng)建以及如何組織的。有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。不難發(fā)現(xiàn),簡單工廠模式的缺點(diǎn)也正體現(xiàn)在其工廠類上,由于工廠類集中了所有實(shí)例的創(chuàng)建邏輯,所以“高聚”方面做的并不好。

42、另外,當(dāng)系統(tǒng)中的具體產(chǎn)品類不斷增多時(shí),可能會(huì)出現(xiàn)要求工廠類也要做相應(yīng)的修改,擴(kuò)展性并不很好。 2.2.3案例 include "iostream"using namespace std;/思想: 核心思想是用一個(gè)工廠,來根據(jù)輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual函數(shù)得到不同的結(jié)果。/元素分析:/抽象產(chǎn)品類:水果類/具體的水果了:香蕉類、蘋果類、梨子/優(yōu)點(diǎn) 適用于不同情況創(chuàng)建不同的類時(shí)/缺點(diǎn) 客戶端必須要知道基類和工廠類,耦合性差 增加一個(gè)產(chǎn)品,需要修改工廠類class Fruitpublic:virtual void getFruit() = 0;prote

43、cted:private:;class Banana : public Fruitpublic:virtual void getFruit()cout<<"香蕉"<<endl;protected:private:;class Pear : public Fruitpublic:virtual void getFruit()cout<<"梨子"<<endl;protected:private:;class Factory public:static Fruit* Create(char *name)Fruit

44、 *tmp = NULL;if (strcmp(name, "pear") = 0)tmp = new Pear();else if (strcmp(name, "banana") = 0)tmp = new Banana();elsereturn NULL;return tmp;protected:private:;void main41()Fruit *pear = Factory:Create("pear");if (pear = NULL)cout<<"創(chuàng)建pear失敗n"pear->ge

45、tFruit();Fruit *banana = Factory:Create("banana");banana->getFruit();system("pause");2.2.4練習(xí)主要用于創(chuàng)建對象。新添加類時(shí),不會(huì)影響以前的系統(tǒng)代碼。核心思想是用一個(gè)工廠來根據(jù)輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual函數(shù)得到不同的結(jié)果。GOOD:適用于不同情況創(chuàng)建不同的類時(shí)BUG:客戶端必須要知道基類和工廠類,耦合性差(工廠類與基類為關(guān)聯(lián)關(guān)系)#include "iostream"using namespace std;/需求:

46、/模擬四則運(yùn)算;/用操作符工廠類生產(chǎn)操作符(加減乘除), 進(jìn)行結(jié)果運(yùn)算/運(yùn)算符抽象類 COperation/加減乘除具體的類(注意含有2個(gè)操作數(shù))/工廠類CCalculatorFactory /核心思想 用一個(gè)工廠來根據(jù)輸入的條件產(chǎn)生不同的類,然后根據(jù)不同類的virtual函數(shù)得到不同的結(jié)果class COperationpublic:int first;int second;public:virtual double GetResult() = 0;private:;class AddOperation : public COperationpublic:double GetResult()

47、return first + second;private:;class SubOperation : public COperationpublic:double GetResult()return first - second;private:;class CCalculatorFactorypublic:static COperation*CreateOperation(char cOperator)COperation * tmp = NULL;switch(cOperator)case '+':tmp = new AddOperation();break;case &

48、#39;-':tmp = new SubOperation();break;default:tmp = NULL;return tmp;void main()COperation *op1 = CCalculatorFactory:CreateOperation('+');op1->first = 10;op1->second = 20;cout<<op1->GetResult()<<endl;COperation *op2 = CCalculatorFactory:CreateOperation('-');op

49、2->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)品對象的工廠接口,將實(shí)際創(chuàng)建工作推遲到子類當(dāng)中。核心工廠類不再負(fù)責(zé)產(chǎn)品的創(chuàng)建,這樣核心類成為一個(gè)抽象工廠角色,僅負(fù)責(zé)具體工廠子類必須實(shí)現(xiàn)的接口,這樣進(jìn)一步抽象化的好處是使得工廠方法模式可以使系統(tǒng)在不修改

50、具體工廠角色的情況下引進(jìn)新的產(chǎn)品。2.3.2類圖角色和職責(zé)抽象工廠(Creator)角色工廠方法模式的核心,任何工廠類都必須實(shí)現(xiàn)這個(gè)接口。具體工廠( Concrete Creator)角色具體工廠類是抽象工廠的一個(gè)實(shí)現(xiàn),負(fù)責(zé)實(shí)例化產(chǎn)品對象。抽象(Product)角色 工廠方法模式所創(chuàng)建的所有對象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。具體產(chǎn)品(Concrete Product)角色 工廠方法模式所創(chuàng)建的具體實(shí)例對象2.3.3工廠方法模式和簡單工廠模式比較 工廠方法模式與簡單工廠模式在結(jié)構(gòu)上的不同不是很明顯。工廠方法類的核心是一個(gè)抽象工廠類,而簡單工廠模式把核心放在一個(gè)具體類上。 工廠方法模

51、式之所以有一個(gè)別名叫多態(tài)性工廠模式是因?yàn)榫唧w工廠類都有共同的接口,或者有共同的抽象父類。當(dāng)系統(tǒng)擴(kuò)展需要添加新的產(chǎn)品對象時(shí),僅僅需要添加一個(gè)具體對象以及一個(gè)具體工廠對象,原有工廠對象不需要進(jìn)行任何修改,也不需要修改客戶端,很好的符合了“開放封閉”原則。而簡單工廠模式在添加新產(chǎn)品對象后不得不修改工廠方法,擴(kuò)展性不好。工廠方法模式退化后可以演變成簡單工廠模式。 “開放封閉”通過添加代碼的方式,不是通過修改代碼的方式完成功能的增強(qiáng)。#include "iostream"using namespace std;class Fruitpublic:virtual void saynam

52、e()cout<<"fruitn"class FruitFactorypublic:virtual Fruit* getFruit()return new Fruit();/香蕉class Banana : public Fruitpublic:virtual void sayname()cout<<"Banana n"<<endl;/香蕉工廠class BananaFactory : public FruitFactorypublic:virtual Fruit* getFruit()return new Banan

53、a;/蘋果class Apple : public Fruitpublic:virtual void sayname()cout<<"Apple n"<<endl;/蘋果工廠class AppleFactory : public FruitFactorypublic:virtual Fruit* getFruit()return new Apple;void main()FruitFactory * ff = NULL;Fruit *fruit = NULL;/1ff = new BananaFactory();fruit = ff->getF

54、ruit();fruit->sayname();delete fruit;delete ff;/2蘋果ff = new AppleFactory();fruit = ff->getFruit();fruit->sayname();delete fruit;delete ff;cout<<"hello.n"system("pause");2.4抽象工廠2.4.1概念 抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最其一般性的。抽象工廠模式可以向客戶端提供一個(gè)接口,使得客戶端在不必指定產(chǎn)品的具體類型的情況下,能夠創(chuàng)建多個(gè)產(chǎn)品族的產(chǎn)品對象。2.4.2產(chǎn)品族和產(chǎn)品等級結(jié)構(gòu)備注1:工廠模式:要么生產(chǎn)香蕉、要么生產(chǎn)蘋果、要么生產(chǎn)西紅柿;但是不能同時(shí)生產(chǎn)一個(gè)產(chǎn)品組。抽象工廠:能同時(shí)生產(chǎn)一個(gè)產(chǎn)品族。=抽象工廠存在原因解釋:具體工廠在開閉原則下,能生產(chǎn)香蕉/蘋果/梨子; (產(chǎn)品等級結(jié)構(gòu))抽象工廠:在開閉原則下,能生產(chǎn):南方香蕉/蘋果/梨子 (產(chǎn)品族)北方香蕉/蘋果/梨子重要區(qū)別:工廠模式只能生產(chǎn)一個(gè)產(chǎn)品

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論