(Boolan) C++設(shè)計模式 第一周筆記

一、8個重要的設(shè)計原則

①依賴倒置原則(DIP)

高層模塊(穩(wěn)定)不應(yīng)該依賴底層模塊(變化),二者都應(yīng)該依賴于抽象(穩(wěn)定);抽象不應(yīng)該依賴于實現(xiàn)細節(jié),實現(xiàn)細節(jié)應(yīng)該依賴抽象。

②開放封閉原則(OCP)

對擴展開放,對更改封閉

類模塊應(yīng)該是可擴展的,但是不可修改。

以擴展的方式應(yīng)對需求變更。

③單一職責(zé)原則(SRP)

一個類應(yīng)該是僅有一個引起它變化的原因,變化的方向隱含著類的責(zé)任。 該職責(zé)是為避免過于復(fù)雜。

④Listov 替換原則(LSP)

子類必須能夠替換它們的基類(IS-A)

以繼承表達類型抽象

⑤接口隔離原則(ISP)

不應(yīng)該強迫客戶程序依賴它們不用的方法

接口應(yīng)該小而完備

⑥優(yōu)先使用對象組合,而不是類繼承

類繼承通常是“白箱復(fù)用”,對象組合通常是“ 黑箱復(fù)用”。

繼承在某種程度上破壞了封裝性,子類父類耦合度高;而對象組合則只要求被組合的對象具有良好定義的接口,耦合度低。

⑦封裝變化點

使用封裝來創(chuàng)建對象之間的分界層,讓設(shè)計著可以在分界層的一側(cè)進行修改,而不會對另一側(cè)產(chǎn)生不良的影響,從而實現(xiàn)層次間的松耦合。

⑧針對接口編程,而不是針對實現(xiàn)編程。

此條與①對應(yīng),不將變量類型聲明為某個特定的具體類,而是聲明為某個接口。 客戶程序不需獲知對象的具體類型,只需知道對象的接口。

減少系統(tǒng)中各部分的依賴關(guān)系,從而實現(xiàn)“高內(nèi)聚、松耦合”的類型設(shè)計方案。

接口標準化是產(chǎn)業(yè)強盛的標志。

二、策略模式

策略模式

介紹:定義一系列算法,將每一個算法封裝起來,并讓它們可以相互替換。 策略模式讓算法獨立于使用它的客戶而變化,也稱為政策模式(Policy)。

類圖

策略模式

適用場景:一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種。

優(yōu)點:1.策略模式提供了管理相關(guān)的算法族的辦法。 2.策略模式提供了可以替換繼承關(guān)系的辦法。 3.使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。

1、先看看策略模式的官方定義:

The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。 策略模式讓算法獨立于使用它的客戶而獨立變化。 )

策略模式類圖如下:

2、《大話設(shè)計模式》實現(xiàn)策略模式中,使用到了反射。 前面也說過,在C++中實際沒有反射,需要自己實現(xiàn)。 為實現(xiàn)反射,我模仿MFC中RTTI的dynamic調(diào)用,利用鏈表實現(xiàn)了個簡單的反射功能。 代碼如下:

ReflectionFunc.h

#pragma once?

#include "stdafx.h"?

#include ?

#include ?

#include ?

using namespace std;?


typedef void* (*CreateFunc)();?


struct ClassFactory?

{?

? ? std::string m_strName;?

? ? CreateFunc m_pObject;?


? ? static void* GetClassByName(std::string strName);?


? ? static ClassFactory* pFirstClass;?

? ? ClassFactory* m_pNextClass;?

};?


struct MY_CLASSINIT?

{?

? ? MY_CLASSINIT(ClassFactory* pNewClass);?

};?


#define DECLARE_MYCLASS(class_name) \?

? ? static void* CreateObject(class_name);\?

? ? static ClassFactory m_CF##class_name;?


#define IMPLEMENT_MYCLASS(class_name)\?

? ? static char my##class_name[] = #class_name;\?

? ? void* class_name::CreateObject(class_name) { return new class_name; }\?

? ? ClassFactory class_name::m_CF##class_name = {my##class_name, (CreateFunc)class_name::CreateObject};\?

? ? static MY_CLASSINIT _init_##class_name(&class_name::m_CF##class_name);?


ReflectionFunc.cpp

#pragma once?

#include "StdAfx.h"?

#include "ReflectionFunc.h"?


ClassFactory* ClassFactory::pFirstClass = NULL;?


void* ClassFactory::GetClassByName(std::string strName)?

{?

? ? void* pObject=NULL;?

? ? ClassFactory* pClass = pFirstClass;?

? ? for (;pClass!=NULL;pClass=pClass->m_pNextClass)?

? ? {?

? ? ? ? if (pClass->m_strName.compare(strName) == 0)?

? ? ? ? {?

? ? ? ? ? ? pObject = pClass->m_pObject();?

? ? ? ? }?

? ? }?

? ? return pObject;?

}?


MY_CLASSINIT::MY_CLASSINIT(ClassFactory* pNewClass)?

{?

? ? pNewClass->m_pNextClass = ClassFactory::pFirstClass;?

? ? ClassFactory::pFirstClass = pNewClass;?

}?

3、策略模式的其他部分代碼實現(xiàn)如下:

CashContext.h

#pragma once?

#include "StrategyPattern.h"?

#include "CashSuper.h"?

#include ?

using namespace std;?


class STRATEGYPATTERN_API CCashContext?

{?

public:?

CCashContext(void);?

~CCashContext(void);?


void SetBehavior(std::string strClassName, char szParam[]);?

double GetResult(double money);?


private:?

CCashSuper* m_pCashSuper;?

};?

CashContext.cpp

#pragma once?

#include "StdAfx.h"?

#include "CashContext.h"?

#include "ReflectionFunc.h"?


CCashContext::CCashContext(void)?

{?


}?



CCashContext::~CCashContext(void)?

{?


}?


void CCashContext::SetBehavior(std::string strClassName, char szParam[])?

{?

? ? CCashSuper* pCash = (CCashSuper*)ClassFactory::GetClassByName(strClassName);?

? ? if (!pCash) return;?

? ? pCash->SetClassParam(szParam);?

? ? m_pCashSuper = pCash;?

}?


double CCashContext::GetResult(double money)?

{?

? ? return m_pCashSuper->acceptCash(money);?

}?

CashSuper.h

#pragma once?

#include ?

#include "ReflectionFunc.h"?


class CCashSuper?

{?

public:?

? ? CCashSuper(void);?

? ? ~CCashSuper(void);?


? ? virtual void SetClassParam(const char* pParam)=0;?

? ? virtual double acceptCash(double money)=0;?

};?

CashRebate.h

#pragma once?

#include "cashsuper.h"?

#include "Utility.h"?


class CCashRebate :public CCashSuper?

{?

public:?

? ? DECLARE_MYCLASS(CCashRebate)?

? ? CCashRebate(void);?

? ? ~CCashRebate(void);?


? ? virtual void SetClassParam(const char* pParam);?

? ? virtual double acceptCash(double money);?


private:?

? ? double m_Rebate;?

};?

CashRebate.cpp

#pragma once?

#include "StdAfx.h"?

#include "CashRebate.h"?


IMPLEMENT_MYCLASS(CCashRebate)?


CCashRebate::CCashRebate(void)?

{?

? ? m_Rebate = 1;?

}?



CCashRebate::~CCashRebate(void)?

{?

}?


double CCashRebate::acceptCash(double money)?

{?

? ? return money * m_Rebate;?

}?


void CCashRebate::SetClassParam(const char* pParam)?

{?

? ? std::string str(pParam);?

? ? std::vector vecStr;?

? ? CUtility::GetInstance().SplitString(str, vecStr);?

? ? m_Rebate = atof(vecStr[0].c_str());?

}?

三、裝飾模式

裝飾模式

介紹:動態(tài)地給一個對象增加一些額外的職責(zé)(Responsibility),就增加對象功能來說, 裝飾模式比生成子類實現(xiàn)更為靈活。 *A_Decorator decoratorA = new A_Decorator (new Object1);

類圖

裝飾者模式

適用場景:需要動態(tài)地將功能添加到對象上時,使用裝飾者模式。 不改變接口但要增強功能。

優(yōu)點:1.裝飾模式與繼承關(guān)系的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。 2.可以通過一種動態(tài)的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的裝飾器,從而實現(xiàn)不同的行為。

裝飾模式:動態(tài)的給一個對象添加一些額外的職能。

網(wǎng)上有個說法感覺比較形象(http://zhousenbiao.com/Design-Patterns/decorator.html):

所謂裝飾, 就是一些對象給主體對象做陪襯。 這是我的理解。 好比說我的辦公桌,需要電腦、電話、文件夾、盆栽等作為裝飾。 那么,辦公桌就是一個主體對象,電腦、電話等裝飾品就是那些做陪襯的對象。 這些辦公用品準備好了,該怎么擺放到辦公桌上呢? 可以有多種方案。 而且,我可以隨時往辦公桌上增加一支簽字筆,增加一枚公章等等。 目前,可歸納如下:A主體對象:辦公桌B裝飾者:電腦、電話、文件夾、盆栽、簽字筆、公章C裝飾者可以裝飾主體對象,即B可以裝飾A什么是裝飾模式? 一個標準的定義是:動態(tài)地將責(zé)任附加到對象上。 若要擴展功能,裝飾者提供了比基礎(chǔ)更有彈性的替代方案。 根據(jù)我的理解,裝飾模式可以這樣定義:能夠動態(tài)地為對象添加功能,同時不會對類進行修改。

網(wǎng)上還有篇裝飾者模式總結(jié)得比較好的:http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html

好了,不多說。 C++代碼如下:

#include "stdafx.h"?

#include ?

#include ?

using namespace std;?


class Person?

{?

public:?

? ? Person(){}?

? ? ~Person(){}?


? ? Person(std::string name)?

? ? {?

? ? ? ? m_strName = name;?

? ? }?


? ? virtual void Show()?

? ? {?

? ? ? ? cout<<"裝扮的"<

? ? }?

private:?

? ? std::string m_strName;?

};?


class Finery: public Person?

{?

public:?

? ? Finery(){}?

? ? ~Finery(){}?


? ? void Decorate(Person* compent)?

? ? {?

? ? ? ? m_component = compent;?

? ? }?


? ? void Show()?

? ? {?

? ? ? ? if (m_component)?

? ? ? ? {?

? ? ? ? ? ? m_component->Show();?

? ? ? ? }?

? ? }?

private:?

? ? Person* m_component;?

};?


class TShirt: public Finery?

{?

public:?

? ? TShirt(){}?

? ? ~TShirt(){}?


? ? void Show()?

? ? {?

? ? ? ? cout<<"T恤 ";?

? ? ? ? Finery::Show();?

? ? }?

};?


class Sneakers: public Finery?

{?

public:?

? ? Sneakers(){}?

? ? ~Sneakers(){}?


? ? void Show()?

? ? {?

? ? ? ? cout<<"破球鞋 ";?

? ? ? ? Finery::Show();?

? ? }?

};?


class Suit : public Finery?

{?

public:?

? ? Suit(){}?

? ? ~Suit(){}?


? ? void Show()?

? ? {?

? ? ? ? cout<<"西裝 ";?

? ? ? ? Finery::Show();?

? ? }?

};?


class Tie : public Finery?

{?

public:?

? ? Tie(){}?

? ? ~Tie(){}?


? ? void Show()?

? ? {?

? ? ? ? cout<<"領(lǐng)帶 ";?

? ? ? ? Finery::Show();?

? ? }?

};?


int _tmain(int argc, _TCHAR* argv[])?

{?

? ? Person* person = new Person("小菜");?

? ? cout<<"第一種裝扮:"<

? ? TShirt* tshirt = new TShirt();?

? ? Tie* tie = new Tie();?

? ? Suit* suit = new Suit();?


? ? tshirt->Decorate(person);?

? ? tie->Decorate(tshirt);?

? ? suit->Decorate(tie);?


? ? suit->Show();?


? ? return 0;?

}?

四、橋模式

1: 橋模式

介紹:將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化。 它是一種對象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。

類圖

橋模式

適用場景:需要將兩組不同的功能組合來用時,可以考慮用“橋”將這兩組功能組合起來。

優(yōu)點:1.分離抽象接口及其實現(xiàn)部分。 2.橋接模式提高了系統(tǒng)的可擴充性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統(tǒng)。

五、 觀察者模式

介紹:定義對象間的一種一對多依賴關(guān)系,使得每當(dāng)一個對象狀態(tài)發(fā)生改變時,其相關(guān)依賴對象皆得到通知并被自動更新。 觀察者模式又叫做發(fā)布-訂閱(Publish/Subscribe)模式

類圖

觀察者模式

適用場景:一個對象的改變將導(dǎo)致其他一個或多個對象也發(fā)生改變,而不知道具體有多少對象將發(fā)生改變,可以降低對象之間的耦合度。

優(yōu)點:1.觀察者模式可以實現(xiàn)表示層和數(shù)據(jù)邏輯層的分離,并定義了穩(wěn)定的消息更新傳遞機制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色。 2.觀察者模式支持廣播通信。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容