(Boolan) C++设计模式 第一周笔记

一、8个重要的设计原则

①依赖倒置原则(DIP)

高层模块(稳定)不应该依赖底层模块(变化),二者都应该依赖于抽象(稳定);抽象不应该依赖于实现细节,实现细节应该依赖抽象。

②开放封闭原则(OCP)

对扩展开放,对更改封闭

类模块应该是可扩展的,但是不可修改。

以扩展的方式应对需求变更。

③单一职责原则(SRP)

一个类应该是仅有一个引起它变化的原因,变化的方向隐含着类的责任。 该职责是为避免过于复杂。

④Listov 替换原则(LSP)

子类必须能够替换它们的基类(IS-A)

以继承表达类型抽象

⑤接口隔离原则(ISP)

不应该强迫客户程序依赖它们不用的方法

接口应该小而完备

⑥优先使用对象组合,而不是类继承

类继承通常是“白箱复用”,对象组合通常是“ 黑箱复用”。

继承在某种程度上破坏了封装性,子类父类耦合度高;而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。

⑦封装变化点

使用封装来创建对象之间的分界层,让设计着可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。

⑧针对接口编程,而不是针对实现编程。

此条与①对应,不将变量类型声明为某个特定的具体类,而是声明为某个接口。 客户程序不需获知对象的具体类型,只需知道对象的接口。

减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案。

接口标准化是产业强盛的标志。

二、策略模式

策略模式

介绍:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。 策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

类图

(Boolan) C++设计模式 第一周笔记_第1张图片

策略模式

适用场景:一个系统需要动态地在几种算法中选择一种。

优点:1.策略模式提供了管理相关的算法族的办法。 2.策略模式提供了可以替换继承关系的办法。 3.使用策略模式可以避免使用多重条件转移语句。

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.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。 策略模式让算法独立于使用它的客户而独立变化。 )

策略模式类图如下:

(Boolan) C++设计模式 第一周笔记_第2张图片

2、《大话设计模式》实现策略模式中,使用到了反射。 前面也说过,在C++中实际没有反射,需要自己实现。 为实现反射,我模仿MFC中RTTI的dynamic调用,利用链表实现了个简单的反射功能。 代码如下:

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、策略模式的其他部分代码实现如下:

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()); 

三、装饰模式

装饰模式

介绍:动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说, 装饰模式比生成子类实现更为灵活。 *A_Decorator decoratorA = new A_Decorator (new Object1);

类图

(Boolan) C++设计模式 第一周笔记_第3张图片

装饰者模式

适用场景:需要动态地将功能添加到对象上时,使用装饰者模式。 不改变接口但要增强功能。

优点:1.装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。 2.可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。

装饰模式:动态的给一个对象添加一些额外的职能。

网上有个说法感觉比较形象(http://zhousenbiao.com/Design-Patterns/decorator.html):

所谓装饰, 就是一些对象给主体对象做陪衬。 这是我的理解。 好比说我的办公桌,需要电脑、电话、文件夹、盆栽等作为装饰。 那么,办公桌就是一个主体对象,电脑、电话等装饰品就是那些做陪衬的对象。 这些办公用品准备好了,该怎么摆放到办公桌上呢? 可以有多种方案。 而且,我可以随时往办公桌上增加一支签字笔,增加一枚公章等等。 目前,可归纳如下:A主体对象:办公桌B装饰者:电脑、电话、文件夹、盆栽、签字笔、公章C装饰者可以装饰主体对象,即B可以装饰A什么是装饰模式? 一个标准的定义是:动态地将责任附加到对象上。 若要扩展功能,装饰者提供了比基础更有弹性的替代方案。 根据我的理解,装饰模式可以这样定义:能够动态地为对象添加功能,同时不会对类进行修改。

网上还有篇装饰者模式总结得比较好的: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<<"领带 "; 

        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: 桥模式

介绍:将抽象部分与它的实现部分分离,使它们都可以独立地变化。 它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。

类图

(Boolan) C++设计模式 第一周笔记_第4张图片

桥模式

适用场景:需要将两组不同的功能组合来用时,可以考虑用“桥”将这两组功能组合起来。

优点:1.分离抽象接口及其实现部分。 2.桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。

五、 观察者模式

介绍:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。 观察者模式又叫做发布-订阅(Publish/Subscribe)模式

类图

(Boolan) C++设计模式 第一周笔记_第5张图片

观察者模式

适用场景:一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

优点:1.观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。 2.观察者模式支持广播通信。

你可能感兴趣的:((Boolan) C++设计模式 第一周笔记)