设计模式(设计原则演化而来)
一、定义
设计模式是软件开发过程中,经过验证的,用于在特定环境下重复出现的,特定问题的解决方案。简单来说,就是特定环境下的固定编程套路。
1.1 解决了什么问题?
只需要修改少量的代码就能适应新的需求。
1.2 设计模式的基础
- 面向对象的设计思想
封装:隐藏实现细节,实现模块化;
继承:无需修改原有类,通过继承的方式实现功能的扩展;
多态:静态多态和动态多态。静态多态指的是函数重载;动态多态指的是子类对父类虚函数的重写。 - 设计原则
面向接口、依赖倒置、开闭原则(对扩展开放,对修改关闭)、单一职责、里氏替换(子类在实现父类虚函数的时候,别忘了父类虚函数本身的某些功能)、接口隔离(依赖注入)、组合优于继承、最少知道原则
1.3 如何学习设计模式
学习目的:
- 在现有代码的基础上,知道如何扩展代码;
- 自己独立做功能抽象时,如何选择设计模式;
学习步骤
- 该设计模式解决了什么问题?稳定点和变化点
- 代码结构长什么样
- 如何在上面扩展代码
- 应用场景
二、设计模式分类
设计模式分为:创建型设计模式和结构型设计模式
2.1 创建型设计举例:
2.1.1 模板方法
- 定义:定义一个算法中的骨架,而将一些步骤延迟到子类。模板方法可以使子类在不改变算法结构的情况下重定义该算法的某些步骤。
- 稳定点:算法骨架;变化点:子流程需要变化
- 代码举例:
#include <iostream> using namespace std; // 开闭 class ZooShow { public: void Show() { // 如果子表演流程没有超时的话,进行一个中场游戏环节;如果超时,直接进入下一个子表演流程 if (Show0()) PlayGame(); Show1(); Show2(); Show3(); } private: void PlayGame() { cout << "after Show0, then play game" << endl; } bool expired; // 对其他用户关闭,但是子类开放的 protected: virtual bool Show0() { cout << "show0" << endl; if (! expired) { return true; } return false; } virtual void Show2() { cout << "show2" << endl; } virtual void Show1() { } virtual void Show3() { } }; // 框架 // 模板方法模式 class ZooShowEx10 : public ZooShow { protected: virtual void Show0() { if (! expired) { return true; } return false; } } class ZooShowEx1 : public ZooShow { protected: virtual bool Show0() { cout << "ZooShowEx1 show0" << endl; if (! expired) { // 里氏替换 return true; } return false; } 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 ZooShowEx10; // 晚绑定还是早绑定 // ZooShow *zs1 = new ZooShowEx1; // ZooShow *zs2 = new ZooShowEx2; zs->Show(); return 0; }
2.1.2 观察者模式
- 定义对象间的一种一对多的依赖关系。当“一”发生变化是,需要通知到所有的“多”。
- 稳定点:一对多的依赖关系;变化点:“多”增加或者删除
- 代码实现
#include <list> #include <algorithm> using namespace std; // class IDisplay { public: virtual void Show(float temperature) = 0; virtual ~IDisplay() {} }; class DisplayA : public IDisplay { public: virtual void Show(float temperature) { cout << "DisplayA Show" << endl; } private: void jianyi(); }; class DisplayB : public IDisplay{ public: virtual void Show(float temperature) { cout << "DisplayB Show" << endl; } }; class DisplayC : public IDisplay{ public: virtual void Show(float temperature) { cout << "DisplayC Show" << endl; } }; class DisplayD : public IDisplay{ public: virtual void Show(float temperature) { cout << "DisplayC Show" << endl; } }; class WeatherData { }; // 应对稳定点,抽象 // 应对变化点,扩展(继承和组合) class DataCenter { public: void Attach(IDisplay * ob) { // } void Detach(IDisplay * ob) { // } void Notify() { float temper = CalcTemperature(); for (auto iter : obs) { iter.Show(temper); } } // 接口隔离 private: WeatherData * GetWeatherData(); float CalcTemperature() { WeatherData * data = GetWeatherData(); // ... float temper/* = */; return temper; } std::list<IDisplay*> obs; }; int main() { // 单例模式 DataCenter *center = new DataCenter; // ... 某个模块 IDisplay *da = new DisplayA(); center->Attach(da); // ... IDisplay *db = new DisplayB(); center->Attach(db); IDisplay *dc = new DisplayC(); center->Attach(dc); center->Notify(); //----- center->Detach(db); center->Notify(); //.... center->Attach(dd); center->Notify(); return 0; }
2.1.3 策略模式
- 定义一系列算法,并把它们封装起来,使它们之间可以相互替换。算法可独立于使用它的客户端而变化:
- 稳定点:客户程序与算法的调用关系;变化点:算法增删和算法内容的改变;
- 代码举例
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; }
文章参考与<零声教育>的C/C++linux服务期高级架构。