一、8个重要的设计原则
①依赖倒置原则(DIP)
高层模块(稳定)不应该依赖底层模块(变化),二者都应该依赖于抽象(稳定);抽象不应该依赖于实现细节,实现细节应该依赖抽象。
②开放封闭原则(OCP)
对扩展开放,对更改封闭
类模块应该是可扩展的,但是不可修改。
以扩展的方式应对需求变更。
③单一职责原则(SRP)
一个类应该是仅有一个引起它变化的原因,变化的方向隐含着类的责任。 该职责是为避免过于复杂。
④Listov 替换原则(LSP)
子类必须能够替换它们的基类(IS-A)
以继承表达类型抽象
⑤接口隔离原则(ISP)
不应该强迫客户程序依赖它们不用的方法
接口应该小而完备
⑥优先使用对象组合,而不是类继承
类继承通常是“白箱复用”,对象组合通常是“ 黑箱复用”。
继承在某种程度上破坏了封装性,子类父类耦合度高;而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。
⑦封装变化点
使用封装来创建对象之间的分界层,让设计着可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
⑧针对接口编程,而不是针对实现编程。
此条与①对应,不将变量类型声明为某个特定的具体类,而是声明为某个接口。 客户程序不需获知对象的具体类型,只需知道对象的接口。
减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案。
接口标准化是产业强盛的标志。
二、策略模式
策略模式
介绍:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。 策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。
类图:
策略模式
适用场景:一个系统需要动态地在几种算法中选择一种。
优点: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.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。 策略模式让算法独立于使用它的客户而独立变化。 )
策略模式类图如下:
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);
类图:
装饰者模式
适用场景:需要动态地将功能添加到对象上时,使用装饰者模式。 不改变接口但要增强功能。
优点: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)模式。
类图:
桥模式
适用场景:需要将两组不同的功能组合来用时,可以考虑用“桥”将这两组功能组合起来。
优点:1.分离抽象接口及其实现部分。 2.桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
五、 观察者模式
介绍:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。 观察者模式又叫做发布-订阅(Publish/Subscribe)模式
类图:
观察者模式
适用场景:一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
优点:1.观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。 2.观察者模式支持广播通信。