1、高层模块不应该依赖底层实现
2、抽象不应该依赖具体实现,实现应该依赖具体实现
1、一个类应该对(组合、继承开发),应该对修改闭合
1、不要将某个变量型设计成特定类,而是声明成接口。
2、客户端不需要知道具体类型,只需要知道具体接口
将稳定点和变化点分离,扩展修改变化点,让稳定点和变化点的实现分离
一个类应该仅有一个引起变化的原因
子类必须能够替换掉他的父类型,主要出现在子类覆盖父类实现,原来使用父类型程序可能出现错误,覆盖了父类型方法却没有实现父类职责
不应该强迫客户依赖于他们不用的接口
继承耦合性高,组合耦合性低
设计模式遵循以上原则衍生出来的
定义一个操作类的框架,而将一些步骤延迟到子类中,使得子类可以改变这个框架的具体实现,但是主体部分还是由框架限制
某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代
更新表演流程;
最常用的设计模式,子类可以复写父类子流程,使父类的骨架流程丰富;反向控制流程的典型应用;父类 protected 保护子类需要复写的子流程;这样子类的子流程只能父类来调用
从代码中可以看出,用户只能调用Show方法,而且后续show1、show2、show3会越来越大
#include
using namespace std;
#if 0
class ZooShow {
public:
void Show0() {
cout << "show0" << endl;
}
void Show2() {
cout << "show2" << endl;
}
};
class ZooShowEx {
public:
void Show1() {
cout << "show1" << endl;
}
void Show3() {
cout << "show3" << endl;
}
};
// 不满足单一职责 , 开 扩展 修改闭原则
// 动物园固定流程,迭代创新
// 稳定和变化 一定的方向上变化
#else if 2
class ZooShow {
public:
ZooShow(int type = 1) : _type(type) {}
public:
void Show() {
if (Show0())
PlayGame(); // 里氏替换
Show1();
Show2();
Show3();
}
// 接口隔离 不要让用户去选择它们不需要的接口
private:
void PlayGame() {
cout << "after Show0, then play game" << endl;
}
private:
bool Show0() {
cout << _type << " show0" << endl;
return true;
}
void Show1() {
if (_type == 1) {
cout << _type << " Show1" << endl;
} else if (_type == 2) {
cout << _type << " Show1" << endl;
} else if (_type == 3) {
}
}
void Show2() {
if (_type == 20) {
}
cout << "base Show2" << endl;
}
void Show3() {
if (_type == 1) {
cout << _type << " Show1" << endl;
} else if (_type == 2) {
cout << _type << " Show1" << endl;
}
}
private:
int _type;
};
#endif
int main () {
#if 0
ZooShow *zs = new ZooShow;
ZooShowEx *zs1 = new ZooShowEx;
zs->Show0();
zs1->Show1();
zs->Show2();
zs1->Show3();
#else if 2
ZooShow *zs = new ZooShow(1);
zs->Show();
#endif
return 0;
}
遵循上面所说,父类控制主体结构,通过protected保护下面的方法,只有子类可以重写,用户不能调用,所以,后续扩展show1、show2、show3就是特别方便
#include
using namespace std;
// 不满足开闭原则 对扩展开放 继承(虚函数覆盖)
// 扩展功能:继承 (虚函数覆盖) 组合
class ZooShow {
public:
void Show() {
if (Show0())
PlayGame();
Show1();
Show2();
Show3();
}
private:
void PlayGame() {
cout << "after Show0, then play game" << endl;
}
protected:
virtual bool Show0(){
cout << "show0" << endl;
return true;
}
virtual void Show2(){
cout << "show2" << endl;
}
virtual void Show1() {
}
virtual void Show3() {
}
};
class ZooShowEx1 : public ZooShow {
protected:
virtual bool Show0(){
cout << "show1" << endl;
return true;
}
virtual void Show2(){
cout << "show3" << endl;
}
};
class ZooShowEx2 : public ZooShow {
protected:
virtual void Show1(){
cout << "show1" << endl;
}
virtual void Show2(){
cout << "show3" << endl;
}
};
class ZooShowEx3 : public ZooShow {
protected:
virtual void Show1(){
cout << "show1" << endl;
}
virtual void Show3(){
cout << "show3" << endl;
}
virtual void Show4() {
//
}
};
/*
*/
int main () {
ZooShow *zs = new ZooShowEx3;
// ZooShow *zs1 = new ZooShowEx1;
// ZooShow *zs2 = new ZooShowEx2;
zs->Show();
return 0;
}
定义一组一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发送改变时候所依赖他的对象都得到通知和更新
气象站发布数据给数据中,数据中心通过处理,将气象站的数据更新到多个终端设备上
观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系松耦合;
观察者自己决定是否订阅通知,目标对象并不关注谁订阅了;
观察者不要依赖通知顺序,目标对象也不知道通知顺序;
常用在基于事件的ui框架中,也是 MVC 的组成部分;
常用在分布式系统中、actor框架中;
从代码中可以看出,没添加一个终端设备,都会调用数据中心的接口,然后进行显示,显然与我们的初衷违背了,我们初衷是,气象中心将数据给到,数据中心进行计算,计算完之后下发给所有的终端,在这个过程中不关心当前有多少终端设备,也不关心终端设备收到这个数据做什么具体的定制化操作。
class DisplayA {
public:
void Show(float temperature);
};
class DisplayB {
public:
void Show(float temperature);
};
class DisplayC {
public:
void Show(float temperature);
}
class WeatherData {
};
class DataCenter {
public:
float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
private:
WeatherData * GetWeatherData(); // 不同的方式
};
// 订阅发布
int main() {
DataCenter *center = new DataCenter;
DisplayA *da = new DisplayA;
DisplayB *db = new DisplayB;
DisplayC *dc = new DisplayC;
float temper = center->CalcTemperature();
da->Show(temper);
db->Show(temper);
dc->Show(temper);
return 0;
}
// 终端变化(增加和删除) 数据中心 不应该受终端变化的影响
通过一个抽象类,规定了所有终端设备必须实现这个类,每个子类可以根据自己需要做一些定制化的开发,数据中心通过遍历终端容器进行数据下发。
#include
//
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature);
private:
void jianyi();
};
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature);
};
class DisplayC : public IDisplay{
public:
virtual void Show(float temperature);
};
class WeatherData {
};
class DataCenter {
public:
void Attach(IDisplay * ob);
void Detach(IDisplay * ob);
void Notify() {
float temper = CalcTemperature();
for (auto iter = obs.begin(); iter != obs.end(); iter++) {
(*iter)->Show(temper);
}
}
// 接口隔离
private:
virtual WeatherData * GetWeatherData();
virtual float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
std::vector<IDisplay*> obs;
};
int main() {
DataCenter *center = new DataCenter;
IDisplay *da = new DisplayA();
IDisplay *db = new DisplayB();
IDisplay *dc = new DisplayC();
center->Attach(da);
center->Attach(db);
center->Attach(dc);
center->Notify();
//-----
center->Detach(db);
center->Notify();
return 0;
}
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用
它的客户程序而变化。 ——《设计模式》 GoF
某商场节假日有固定促销活动,为了加大促销力度,现提升国庆节促销活动规格;
策略模式提供了一系列可重用的算法,从而可以使得类型在运⾏时方便地根据需要在各个算法之间
进行切换;
策略模式消除了条件判断语句;也就是在解耦合
节日的增加会让这个函数类的if else越来越多
enum VacationEnum {
VAC_Spring,
VAC_QiXi,
VAC_Wuyi,
VAC_GuoQing,
VAC_ShengDan,
};
// 稳定点 变化点
// 如果一个 只有稳定点 需不需要设计模式
// 如果 全是变化点 怎么办? c++ 游戏开发 脚本语言
class Promotion {
VacationEnum vac;
public:
double CalcPromotion(){
if (vac == VAC_Spring {
// 春节
}
else if (vac == VAC_QiXi) {
// 七夕
}
else if (vac == VAC_Wuyi) {
// 五一
}
else if (vac == VAC_GuoQing) {
// 国庆
}
else if (vac == VAC_ShengDan) {
}
}
};
class Context {
};
class ProStategy {
public:
virtual double CalcPro(const Context &ctx) = 0;
virtual ~ProStategy();
};
// cpp
class VAC_Spring : public ProStategy {
public:
virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_QiXi : public ProStategy {
public:
virtual double CalcPro(const Context &ctx){}
};
class VAC_QiXi1 : public VAC_QiXi {
public:
virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_Wuyi : public ProStategy {
public:
virtual double CalcPro(const Context &ctx){}
};
// cpp
class VAC_GuoQing : public ProStategy {
public:
virtual double CalcPro(const Context &ctx){}
};
class VAC_Shengdan : public ProStategy {
public:
virtual double CalcPro(const Context &ctx){}
};
class Promotion {
public:
Promotion(ProStategy *sss) : s(sss){}
~Promotion(){}
double CalcPromotion(const Context &ctx){
return s->CalcPro(ctx);
}
private:
ProStategy *s;
};
int main () {
Context ctx;
ProStategy *s = new VAC_QiXi1();
Promotion *p = new Promotion(s);
p->CalcPromotion(ctx);
return 0;
}