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

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

①依賴倒置原則(DIP)
高層模塊(穩(wěn)定)不應(yīng)該依賴底層模塊(變化),二者都應(yīng)該依賴于抽象(穩(wěn)定);抽象不應(yīng)該依賴于實(shí)現(xiàn)細(xì)節(jié),實(shí)現(xiàn)細(xì)節(jié)應(yīng)該依賴抽象。
②開(kāi)放封閉原則(OCP)
對(duì)擴(kuò)展開(kāi)放,對(duì)更改封閉
類模塊應(yīng)該是可擴(kuò)展的,但是不可修改。
以擴(kuò)展的方式應(yīng)對(duì)需求變更。
③單一職責(zé)原則(SRP)
一個(gè)類應(yīng)該是僅有一個(gè)引起它變化的原因,變化的方向隱含著類的責(zé)任。該職責(zé)是為避免過(guò)于復(fù)雜。
④Listov 替換原則(LSP)
子類必須能夠替換它們的基類(IS-A)
以繼承表達(dá)類型抽象
⑤接口隔離原則(ISP)
不應(yīng)該強(qiáng)迫客戶程序依賴它們不用的方法
接口應(yīng)該小而完備
⑥優(yōu)先使用對(duì)象組合,而不是類繼承
類繼承通常是“白箱復(fù)用”,對(duì)象組合通常是“黑箱復(fù)用”。
繼承在某種程度上破壞了封裝性,子類父類耦合度高;而對(duì)象組合則只要求被組合的對(duì)象具有良好定義的接口,耦合度低。
⑦封裝變化點(diǎn)
使用封裝來(lái)創(chuàng)建對(duì)象之間的分界層,讓設(shè)計(jì)著可以在分界層的一側(cè)進(jìn)行修改,而不會(huì)對(duì)另一側(cè)產(chǎn)生不良的影響,從而實(shí)現(xiàn)層次間的松耦合。
⑧針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程。
此條與①對(duì)應(yīng),不將變量類型聲明為某個(gè)特定的具體類,而是聲明為某個(gè)接口??蛻舫绦虿恍璜@知對(duì)象的具體類型,只需知道對(duì)象的接口。
減少系統(tǒng)中各部分的依賴關(guān)系,從而實(shí)現(xiàn)“高內(nèi)聚、松耦合”的類型設(shè)計(jì)方案。
接口標(biāo)準(zhǔn)化是產(chǎn)業(yè)強(qiáng)盛的標(biāo)志。
二、策略模式
策略模式
介紹:定義一系列算法,將每一個(gè)算法封裝起來(lái),并讓它們可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而變化,也稱為政策模式(Policy)。

類圖

策略模式

適用場(chǎng)景:一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。
優(yōu)點(diǎn):1.策略模式提供了管理相關(guān)的算法族的辦法。2.策略模式提供了可以替換繼承關(guān)系的辦法。 3.使用策略模式可以避免使用多重條件轉(zhuǎn)移語(yǔ)句。
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.(策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來(lái),而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。)
策略模式類圖如下:


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

#pragma once  
#include "stdafx.h"  
#include <string>  
#include <map>  
#include <vector>  
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、策略模式的其他部分代碼實(shí)現(xiàn)如下:
CashContext.h


#pragma once  
#include "StrategyPattern.h"  
#include "CashSuper.h"  
#include <string>  
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 <vector>  
#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<string> vecStr;  
    CUtility::GetInstance().SplitString(str, vecStr);  
    m_Rebate = atof(vecStr[0].c_str());  
}  

三、裝飾模式
裝飾模式
介紹:動(dòng)態(tài)地給一個(gè)對(duì)象增加一些額外的職責(zé)(Responsibility),就增加對(duì)象功能來(lái)說(shuō),裝飾模式比生成子類實(shí)現(xiàn)更為靈活。 *A_Decorator decoratorA = new A_Decorator (new Object1);

類圖

裝飾者模式

適用場(chǎng)景:需要動(dòng)態(tài)地將功能添加到對(duì)象上時(shí),使用裝飾者模式。不改變接口但要增強(qiáng)功能。
優(yōu)點(diǎn):1.裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能,但是裝飾模式可以提供比繼承更多的靈活性。2.可以通過(guò)一種動(dòng)態(tài)的方式來(lái)擴(kuò)展一個(gè)對(duì)象的功能,通過(guò)配置文件可以在運(yùn)行時(shí)選擇不同的裝飾器,從而實(shí)現(xiàn)不同的行為。

裝飾模式:動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的職能。
網(wǎng)上有個(gè)說(shuō)法感覺(jué)比較形象(http://zhousenbiao.com/Design-Patterns/decorator.html):
所謂裝飾,就是一些對(duì)象給主體對(duì)象做陪襯。這是我的理解。好比說(shuō)我的辦公桌,需要電腦、電話、文件夾、盆栽等作為裝飾。那么,辦公桌就是一個(gè)主體對(duì)象,電腦、電話等裝飾品就是那些做陪襯的對(duì)象。這些辦公用品準(zhǔn)備好了,該怎么擺放到辦公桌上呢?可以有多種方案。而且,我可以隨時(shí)往辦公桌上增加一支簽字筆,增加一枚公章等等。目前,可歸納如下:A主體對(duì)象:辦公桌B裝飾者:電腦、電話、文件夾、盆栽、簽字筆、公章C裝飾者可以裝飾主體對(duì)象,即B可以裝飾A什么是裝飾模式?一個(gè)標(biāo)準(zhǔn)的定義是:動(dòng)態(tài)地將責(zé)任附加到對(duì)象上。若要擴(kuò)展功能,裝飾者提供了比基礎(chǔ)更有彈性的替代方案。根據(jù)我的理解,裝飾模式可以這樣定義:能夠動(dòng)態(tài)地為對(duì)象添加功能,同時(shí)不會(huì)對(duì)類進(jìn)行修改。

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

好了,不多說(shuō)。C++代碼如下:

#include "stdafx.h"  
#include <string>  
#include <iostream>  
using namespace std;  
  
class Person  
{  
public:  
    Person(){}  
    ~Person(){}  
  
    Person(std::string name)  
    {  
        m_strName = name;  
    }  
  
    virtual void Show()  
    {  
        cout<<"裝扮的"<<m_strName<<endl;  
    }  
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<<"第一種裝扮:"<<endl;  
    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: 橋模式
介紹:將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。它是一種對(duì)象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。

類圖

橋模式

適用場(chǎng)景:需要將兩組不同的功能組合來(lái)用時(shí),可以考慮用“橋”將這兩組功能組合起來(lái)。
優(yōu)點(diǎn):1.分離抽象接口及其實(shí)現(xiàn)部分。2.橋接模式提高了系統(tǒng)的可擴(kuò)充性,在兩個(gè)變化維度中任意擴(kuò)展一個(gè)維度,都不需要修改原有系統(tǒng)。

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

類圖

觀察者模式

適用場(chǎng)景:一個(gè)對(duì)象的改變將導(dǎo)致其他一個(gè)或多個(gè)對(duì)象也發(fā)生改變,而不知道具體有多少對(duì)象將發(fā)生改變,可以降低對(duì)象之間的耦合度。
優(yōu)點(diǎn):1.觀察者模式可以實(shí)現(xiàn)表示層和數(shù)據(jù)邏輯層的分離,并定義了穩(wěn)定的消息更新傳遞機(jī)制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色。2.觀察者模式支持廣播通信。

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

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

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