C++設計模式基礎教程_第1頁
C++設計模式基礎教程_第2頁
C++設計模式基礎教程_第3頁
C++設計模式基礎教程_第4頁
C++設計模式基礎教程_第5頁
已閱讀5頁,還剩200頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

C/C++與設計模式根底課程

設計模式根底

1設計模式編程根底

1.1設計模式前言

模式

在一定環境中解決某一問題的方案,包括三個根本元素-問題,解決方案和環境。

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

設計模式(Designpattern)

是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計

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

式于己于他人于系統都是多贏的;設計模式使代碼編制真正工程化;

設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。

學習設計模式的意義

提高職業素養,關注學員在行業內的長期開展。

“我眼中的設計模式"

把簡單的問題復雜化(標準化),把環境中的各個局部進行抽象、歸納、解耦合。

不是多神秘的東西,我們初學者也能學的會。要有信心。

學習設計模式的方法

對初學者:

積累案例,大于背類圖。

初級開發人員:

多思考、多梳理,歸納總結;

尊重事物的認知規律,注意事物臨界點的突破。不可急躁。

中級開發人員

適宜的開發環境,尋找適宜的設計模式,解決問題。

多應用

對經典組合設計模式的大量、自由的運用。要不斷的追求。

設計模式的分類

GangofFour的**DesignPatterns:ElementsofResualbelSoftware"書將設計模式歸納為

三大類型,共23種。

創立型模式:通常和對象的創立有關,涉及到對象實例化的方式。(共5種模式)

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

行為型模式:用來對類或對象怎樣交互和怎樣分配職責進行描述。(共11種模式)

創立型模式用來處理對象的創立過程,主要包含以下5種設計模式:

1,工廠方法模式(FactoryMethodPattern)的用意是定義一個創立產品對象的工廠接口,

將實際創立工作推遲到子類中。

2,抽象工廠模式(AbstractFactoryPattern)的意圖是提供-一個創立一系列相關或者相互依

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

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

構建過程可以創立不同的表示。

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

型創立新的對象。

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

問點。

結構型模式用來處理類或者對象的組合,主要包含以下7種設計模式:

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

7,裝飾者模式(DecoratorPattern)動態的給一個對象添加一些額外的職責。就增加功能來

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

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

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

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

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

構。使得用戶對單個對象和組合對象的使用具有一致性。

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

了一個高層接口,這個接口使得這一子系統更加容易使用。

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

行為型模式用來對類或對象怎樣交互和怎樣分配職責進行描述,主要包含以下11種設計模

式:

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

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

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

求對客戶端進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。

15,責任鏈模式(ChainofResponsibilityPattern),在該模式里,很多對象由每—個對象對其

下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理

此請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。

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

可以互換。

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

結者使各個對象不需要顯示的相互調用,從而使其耦合性松散,而且可以獨立的改變他們

之間的交互。

18,觀察者模式(ObserverPattern)定義對象間的一種一對多的依賴關系,當一個對象的狀

態發生改變時,所有依賴于它的對象都得到通知并被自動更新。

19,備忘錄模式(MementoPattern)是在不破壞封裝的前提下,捕獲一個對象的內部狀態,

并在該對象之外保存這個狀態。

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

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

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

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

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

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

素,而又不需要暴露該對象的內部表示。

1.2設計模式根本原那么

最終目的:高內聚,低耦合

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

類的改動是通過增加代碼進行的,而不是修改源代碼。

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

類的職責要單一,對外只提供一種功能,而引起類變化的原因都應該只有一個。

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

依賴于抽象(接口),不要依賴具體的實現(類),也就是針對接口編程。

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

不應該強迫客戶的程序依賴他們不需要的接口方法。一個接口應該只提供一種對外功能,

不應該把所有操作都封裝到一個接口中去。

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

任何抽象類出現的地方都可以用他的實現類進行替換。實際就是虛擬機制,語言級別實

現面向對象功能。

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

如果使用繼承,會導致父類的任何變換都可能影響到子類的行為。

如果使用對象組合,就降低了這種依賴關系。

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

一個對象應當對其他對象盡可能少的了解,從而降低各個對象之間的耦合,提高系統的

可維護性。例如在一個程序中,各個模塊之間相互調用時,通常會提供一個統一的接口來實

現。這樣其他模塊不需要了解另外一個模塊的內部實現細節,這樣當一個模塊內部的實現發

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

案例圖

開閉原那么案例

繁忙

的業銀行業務員

務員1.付款

2.取款儲戶

3.轉賬

4.申購基金

5.其他業務

負責存款負責取款負責轉賬

依賴倒轉

1)

傳統的過程式設計傾向于使高層次的模塊依賴于低層次的模塊,抽象層依賴

于具體的層次。

2)

邏輯

業務

高層

法那么

迪米特

生人說

1)和陌

行解耦

生人進

人和陌

讓某

說話

生人

象陌

和抽

某人

結合

那么

轉原

賴倒

與依

3)

2創立型模式

2.1單例模式

2.2.1概念

單例模式是一種對象創立型模式,使用單例模式,可以保證為一個類只生成唯一的實例

對象。也就是說,在整個程序空間中,該類只存在一個實例對象。

GOF對單例模式的定義是:保證一個類、只有一個實例存在,同時提供能對該實例加以

訪問的全局訪問方法。

單例模式(Singleton)結構圖

Singleton

Singleton類,定義一個GetInstance操作,允許

-instance:Singleton客戶訪問它的唯一實例Getlnstance是一個靜態

-Singleton0方法,主要負責創建自己的唯一實例

+GetInstance0

2.2.2為什么使用單例模式

在應用系統開發中,我們常常有以下需求:

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

操作同一個對象

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

-大規模系統中,為了性能的考慮,需要節省對象的創立時間等等。

因為Singleton模式可以保證為一個類只生成唯一的實例對象,所以這些情況,Singleton模

式就派上用場了。

2.2.3實現單例步驟常用步驟

a)構造函數私有化

b)提供一個全局的靜態方法(全局訪問點)

c)在類中定義一個靜態指針,指向本類的變量的靜態變量指針

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

懶漢式

#include<iostream>

usingnamespacestd;

〃懶漢式

classSingelton

(

private:

Singelton()

(

m_singer=NULL;

m_count=0;

cout?”構造函數Singelton...do"?endl;

)

public:

staticSingelton*getlnstance()

(

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

(

m_singer=newSingelton;

}

returnm_singer;

)

staticvoidprintT()

(

cout?"m_count:"?m_count?endl;

)

private:

staticSingelton*m_singer;

staticintm_count;

);

Singelton*Singelton::m_singer=NULL;〃懶漢式并沒有創立單例對象

intSingelton::m_count=0;

voidmain01_l()

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

Singelton*pl=Singelton::getlnstance();〃只有在使用的時候,才去創立對象。

Singelton*p2=Singelton::getlnstance();

if(pl!=p2)

(

cout?”不是同一個對象"?endl;

)

else

(

cout?”是同一個對象“?endl;

)

pl->printT();

p2->printT();

system("pause");

return;

llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll

〃俄漢式

classSingelton2

private:

Singelton2()

(

m__singer=NULL;

m_count=0;

cout?”構造函數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;〃不管你創立不創立實例,均把實例new

出來

intSingelton2::m_count=0;

voidmain()

(

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

Singelton2*pl=Singelton2::getlnstance();〃只有在使用的時候,才去創立對象。

Singelton2*p2=Singelton2::getlnstance();

if(pl!=p2)

cout?"不是同一個對象"?endl;

)

else

(

cout?”是同一個對象“?endl;

}

pl->printT();

p2->printT();

Singelton2::Freelnstance();

Singelton2::Freelnstance();

system("pause");

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

〃:L"懶漢"模式雖然有優點,但是每次調用Getlnstance()靜態方法時,必須判斷

//NULL==mjnstance,使程序相對開銷增大。

//2多線程中會導致多個實例的產生,從而導致運行代碼不正確以及內存的泄露。

//3提供釋放資源的函數

討論:這是因為C++中構造函數并不是線程平安的。

C++中的構造函數簡單來說分兩步:

第一步:內存分配

第二步:初始化成員變量

由于多線程的關系,可能當我們在分配內存好了以后,還沒來得急初始化成員變量,

就進行線程切換,另外一個線程拿到所有權后,由于內存已經分配了,但是變量初始化還

沒進行,因此打印成員變量的相關值會發生不一致現象.

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

mainINFINITE).

該函:?數作用.

告訴內核,客待子線程部結束完畢以

'后,:才把主進程main,給陜醒,指向

linux:pthread_create(..,緩退函起體)2)進程結束了

上層應用

WaitForSingleObject

核win內核

1次調用2次返回

2寫時復制

子進程和父進程在各自的進程空間

內返回...

進程空間:堆棧的內存四區

#include"stdafx.h"

#include"windows.h"

include"winbase.h"

#include<process.h>

#include"iostream"

usingnamespacestd;

classSingelton

(

private:

Singelton()

(

count++;

cout?"Singelton構造函數begin\n"?endl;

Sleep(lOOO);

cout?"Singelton構造函數end\n"?endl;

)

private:

〃防止拷貝構造和賦值操作

Singelton(constSingelton&obj){;}

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

public:

staticSingelton*getSingelton()

(

〃。懶漢”模式雖然有優點,但是每次調用Getlnstance。靜態方法時,必須判斷

//NULL==m_instance,使程序相對開銷增大。

//2多線程中會導致多個實例的產生,從而導致運行代碼不正確以及內存的泄露。

//3提供釋放資源的函數

returnsingle;

)

staticSingelton*releaseSingelton()

(

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

(

釋放資源\n“《endl;

deletesingle;

single=NULL;

}

returnsingle;

)

voidpirntS()〃測試函數

(

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

)

private:

staticSingelton*single;

staticintcount;

);

//note靜態變量類外初始化

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;

)

)

〃等待所有的子線程都運行完畢后,才執行這個代碼

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

(

WaitForSingleObject(hThread[i],INFINITE);

}

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

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

(

//CloseHandle(hThread[i]);

}

Singelton::releaseSingelton();

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

system("pause");

return0;

}

2.2.6多線程下懶漢式單例的Double-CheckedLocking優化

新建MFC對話框應用程序。

方便使用臨界區類對象,同步線程

//MFCDiagram應用程序

#include"stdafx.h"

#include”01單例優化.h"

#include"01單例優化Dlg.h"

#include"afxdialogex.h"

#include"iostream"

usingnamespacestd;

〃臨界區

staticCCriticalSectioncs;

//manpthread_create()

classSingleton

(

private:

Singleton()

(

TRACE("Singletonbegin\n");

Sleep(lOOO);

TRACE("Singletonend\n");

)

Singleton(constSingleton&);

Singleton&operator=(constSingleton&);

public:

staticvoidprintV()

(

TRACE("printV..\n");

)

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

NULL)”

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

//1)第1個、2個、3個線程執行第一個檢查,都有可能進入黃色區域(臨界區)

〃2)假設第1個線程進入到臨界區,第2個、第3個線程需要等待

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

〃4)假假設第2個線程進入臨界區,此時第2個線程需要再次判斷if(plnstance==NULL)",

假設第一個線程已經創立實例;第2個線程就不需要再次創立了。保證了單例;

//5)同樣道理,假設第2個線程,cs.unlock。后,第3個線程會競爭執行臨界區代碼;此時

第3個線程需要再次判斷if(plnstance==NULL)?通過檢查發現實例已經new出來,就不需

要再次創立;保證了單例。

staticSingleton*lnstantialize()

{

iffplnstance==NULL)//doublecheck

(

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

if(plnstance==NULL)

plnstance=newSingleton();

)

cs.Unlock();

}

returnplnstance;

)

staticSingleton*plnstance;

);

Singleton*Singleton::plnstance=0;

voidCMyOl單例優化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單例優化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("等待線程結束\n");

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

//CloseHandle(hThread[i]);

}

//Singelton::releaseSingelton();

TRACE("ddddd\n");

2.2.7程序并發機制擴展閱讀

程序的并發執行往往帶來與時間有關的錯誤,甚至引發災難性的后果。這需要

引入同步機制。使用多進程與多線程時,有時需要協同兩種或多種動作,此過程就

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

同步訪問,因為多個線程在共享資源時如果發生訪問沖突通常會帶來不正確的后果。

例如,一個線程正在更新一個結構,同時另一個線程正試圖讀取同一個結構。結果,

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

有時要求確保線程之間的動作以指定的次序發生,如一個線程需要等待由另外一個

線程所引起的事件。

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

每種對象相對于線程有兩種狀態一一信號狀態(signalstate)和非信號狀態(nonsignal

state)?當相關聯的同步對象處于信號狀態時,線程可以執行(訪問共享資源),反

之必須等待。這四種同步對象是:

(1)事件對象(Event)。事件對象作為標志在線程間傳遞信號。一個或多個線

程可等待一個事件對象,當指定的事件發生時,事件對象通知等待線程可以開始執

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

⑵臨界區(CriticalSection).臨界區對象通過提供一個進程內所有線程必須

共享的對象來控制線程。只有擁有那個對象的線程可以訪問保護資源。在另一個線

程可以訪問該資源之前,前一個線程必須釋放臨界區對象,以便新的線程可以索取

對象的訪問權。

(3)互斥量(MutexSemaphore)。互斥量的工作方式非常類似于臨界區,只是

互斥量不僅保護一個進程內為多個線程使用的共享資源,而且還可以保護系統中兩

個或多個進程之間的的共享資源。

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

它是通過計數器來實現的,初始化時賦予計數器以可用資源數,當將信號量提供應

一個線程時,計數器的值減1,當一個線程釋放它時,計數器值加1。當計數器值小

于等于0時,相應線程必須等待。信號量是Windows98同步系統的核心。從本質上

講,互斥量是信號量的一種特殊形式。

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

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

后臺任務。

同步問題是多線程編程中最復雜的問題,后面的linux系統編程中,還會有更深入的介紹。

2.2.8總結

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

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

譯器,多線程,C++語言標準等方面的內容。本專題參考的資料如下:

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

2、MSDN,有關線程同步interlocked相關的知識。

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

單例模式的實現。

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

Meyers),解釋了由于編譯器的優化,導致auto_ptr.reset函數不平安,shared_ptr

有類似情況。我們防止使用reset函數。

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

6、四人幫的經典之作:設計模式

7、windows核心編程(JeffreyRichter)

2.2簡單工廠模式

221什么是簡單工廠模式

簡單工廠模式屬于類的創立型模式,又叫做靜態工廠方法模式。通過專門定義一個類來負

責創立其他類的實例,被創立的實例通常都具有共同的父類。

2.2.2模式中包含的角色及其職責

1.工廠(Creator)角色

簡單工廠模式的核心,它負責實現創立所有實例的內部邏輯。工廠類可以被外界直接調

用,創立所需的產品對象。

2.抽象(Product)角色

簡單工廠模式所創立的所有對象的父類,它負責描述所有實例所共有的公共接口。

3.具體產品(ConcreteProduct)角色

簡單工廠模式所創立的具體實例對象

〃依賴:一個類的對象當另外一個類的函數參數或者是返回值

3簡單工廠模式的優缺點

在這個模式中,工廠類是整個模式的關鍵所在。它包含必要的判斷邏輯,能夠根據外界

給定的信息,決定究竟應該創立哪個具體類的對象。用戶在使用時可以直接根據工廠類去創

立所需的實例,而無需了解這些對象是如何創立以及如何組織的。有利于整個軟件體系結構

的優化。不難發現,簡單工廠模式的缺點也正表達在其工廠類上,由于工廠類集中了所有實

例的創立邏輯,所以“高內聚”方面做的并不好。另外,當系統中的具體產品類不斷增多時,

可能會出現要求工廠類也要做相應的修改,擴展性并不很好。

2.2.3案例

include"iostream"

usingnamespacestd;

〃思想:核心思想是用一個工廠,來根據輸入的條件產生不同的類,然后根據不同類的virtual

函數得到不同的結果。

〃元素分析:

〃抽象產品類:水果類

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

〃優點適用于不同情況創立不同的類時

〃缺點客戶端必須要知道基類和工廠類,耦合性差增加一個產品,需要修改工廠類

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<<"創立pear失敗\n”;

}

pear->getFruit();

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

banana->getFruit();

system("pause");

2.2.4練習

主要用于創立對象。新添加類時,不會影響以前的系統代碼。核心思想是用一個工廠來根據

輸入的條件產生不同的類,然后根據不同類的virtual函數得到不同的結果。

GOOD:適用于不同情況創立不同的類時

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

?*IT?

(工廠類與基類為關聯關系〕

#include"iostream"

usingnamespacestd;

〃需求:〃模擬四那么運算;

〃用操作符工廠類生產操作符(加減乘除),進行結果運算

〃運算符抽象類COperation

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

〃工廠類CCalculatorFactory

〃核心思想用一個工廠來根據輸入的條件產生不同的類,然后根據不同類的virtual函數得

到不同的結果

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概念

工廠方法模式同樣屬于類的創立型模式又被稱為多態工廠模式。工廠方法模式的意義是

定義一個創立產品對象的工廠接口,將實際創立工作推遲到子類當中。

核心工廠類不再負責產品的創立,這樣核心類成為一個抽象工廠角色,僅負責具體工廠子類

必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可以使系統在不修改具體工

廠角色的情況下引進新的產品。

2.3.2類圖角色和職責

抽象工廠(Creator)角色

工廠方法模式的核心,任何工廠類都必須實現這個接口。

具體工廠(ConcreteCreator)角色

具體工廠類是抽象工廠的一個實現,負責實例化產品對象。

抽象(Product)角色

工廠方法模式所創立的所有對象的父類,它負責描述所有實例所共有的公共接口。

具體產品(ConcreteProduct)角色

工廠方法模式所創立的具體實例對象

工廠方法模式(FactoryMethod)結構圖

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

工廠方法模式與簡單工廠模式在結構上的不同不是很明顯。工廠方法類的核心是一個抽

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

工廠方法模式之所以有一個別名叫多態性工廠模式是因為具體工廠類都有共同的接口,

或者有共同的抽象父類。

當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體對象以及一個具體工廠對

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

原那么。而簡單工廠模式在添加新產品對象后不得不修改工廠方法,擴展性不好。工廠方法

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

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

#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概念

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

客戶端提供一個接口,使得客戶端在不必指定產品的具體類型的情況下,能夠創立多個產品

族的產品對象。

2.4.2產品族和產品等級結構

產品族

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

個產品組。抽象工廠:能同時生產一個產品族。===?抽象工廠存在原因

解釋:具體工廠在開閉原那么下,能生產香蕉/蘋果/梨子;(產品等級結構)

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

北方香蕉/蘋果/梨子

重要區別:

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

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

2.4.3模式中包含的角色及其職責

1.抽象工廠(Creator)角色

抽象工廠模式的核心,包含對多個產品結構的聲明,任何工廠類都必須實現這個接口。

2.具體工廠(ConcreteCreator)角色

具體工廠類是抽象工廠的一個實現,負責實例化某個產品族中的產品對象。

3.抽象(Product)角色

抽象模式所創立的所有對象的父類,它負責描述所有實例所共有的公共接口。

4.具體產品(ConcreteProduct)角色

抽象模式所創立的具體實例對象

抽象工廠模式(AbstractFactory)結構圖

2.4.4案例

classFruit

(

溫馨提示

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

評論

0/150

提交評論