后端技术_创建型设计模式
最近更新:2024-09-23
|
字数总计:2.4k
|
阅读估时:10分钟
|
阅读量:次
- 设计模式基础
- 是什么
- 由来
- 解决了什么问题
- 基础
- 学习
- 具体设计模式
- 模板方法
- 举例
- 观察者模式
- 举例
- 策略模式
- 举例
设计模式基础
是什么
- 设计模式:软件开发中,经过验证,用于解决在特定环境下,重复出现的,特定问题的解决方案;
- 即:解决问题的固定套路;
- 慎用设计模式;
由来
解决了什么问题
- 前提:具体的需求既有稳定点又有变化点;
- 没有必要使用:1. 全是稳定点;2. 全是变化点(游戏,脚本语言);
- 期望修改少量的代码,就可以适应需求的变化;
基础
- 面向对象思想:
- 封装(隐藏实现细节,实现模块化)
- 继承(无需修改类的基础上,实现通过对功能的扩展)
- 多态(函数重载:静态多态;虚函数重写:动态多态)
- 设计原则
- 依赖倒置: 高层模块不应该依赖底层模块,两者都应该依赖抽象;抽象不应该依赖具体实现,具体实现应该依赖于抽象;
flowchart TD;
A((自动驾驶系统)) --> B((宝马));
A --> C((丰田));
A --> D((本田));
- 开闭原则,对扩展开放对修改关闭,封装、多态
- 面向接口,封装
- 封装变化点,封装、多态
- 单一职责原则,封装
- 里氏替换,多态
- 接口隔离
- 组合优于继承
- 最小知道原则,封装
学习
- 明确目的
- 在现有设计模式的基础上,扩展代码
- 做功能抽象时,如何选择设计模式
- 学习步骤
- 该设计模式解决了什么问题
- 该设计模式的代码结构是什么
- 符合哪些设计原则
- 如何在上面扩展代码
- 该设计模式有哪些典型应用场景
具体设计模式
模板方法
- 定义:一个操作的算法框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 解决的问题:
- 代码结构
- 基类中有一个骨架流程接口
- 所有子流程对子类开放并且设置为虚函数
- 通过继承多态方法来使用它
- 符合哪些设计原则
- 单一原则
- 开闭原则
- 依赖倒置(子类扩展时,需要依赖基类的虚函数实现;使用者只依赖接口)
- 封装变化点(protected)
- 接口隔离
- 最小知道原则
- 如何扩展
- 实现子类继承基类,复写子流程
- 通过多态调用方式使用
举例
- 背景:某个品牌动物园,有一个套固定的表演流程,但是其中若干个表演子流程可创新替换,以尝试迭代更新表演流程;
- 代码
- 不使用设计模式,但是遵循设计原则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
class ZooShow{ public: ZooShow(int type=1) : _type(type) {} void Show(){ if(Show0()) PlayGame(); Show1(); Show2(); Show3(); } private: void PlayGame(){ cout << "after Show0, then play game" << endl; } bool Show0(){ if(_type == 1){ return true; } else if(_type == 2){ return true; } else if(_type == 3){ return true; } cout << type << " show0" << endl; } 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; };
|
- 使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| 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; zs->Show(); return 0; }
|
观察者模式
- 定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
- 解决的问题
- 稳定点:“一”对“多”的依赖关系,“一”变化“多”跟着变化
- 变化点:“多”赠加;“多”减少;
- 代码结构
- 符合哪些设计模式
- 面向接口编程
- 接口隔离(类与类依赖在一个接口)
- 封装变化点(attach detach)
- 如何扩展代码
- 继承实现接口
- 调用attach(多增加)
- 调用detach(多减少)
举例
- 背景:气象站发布气象资料给数据中心,数据中心通过处理,将气象信息更新到两个不同的显示终端(A和B);
- 未使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| 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: void TempNotify() { DisplayA *da = new DisplayA; DisplayB *db = new DisplayB; DisplayC *dc = new DisplayC; float temper = this->CalcTemperature(); da->Show(temper); db->Show(temper); dc->Show(temper); dc->Show(temper); } private: float CalcTemperature() { WeatherData * data = GetWeatherData(); float temper; return temper; } WeatherData * GetWeatherData(); };
int main() { DataCenter *center = new DataCenter; center->TempNotify(); return 0; }
|
- 使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| 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; }
|
策略模式
- 定义一系列算法,把他们一个个封装起来,并且使他们可相互替换。该模式使得算法那可独立于使用它的客户程序而变化。
- 解决了什么问题
- 代码结构
- 符合哪些设计原则
- 如何扩展代码
举例
- 背景:某商场节假日有固定的促销活动,为了加大促销力度,现提升国庆节促销活动规格;
- 未使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| enum VacationEnum { VAC_Spring, VAC_QiXi, VAC_Wuyi, VAC_GuoQing, VAC_ShengDan, };
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) {
} } };
|
- 使用设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| class Context {
};
class ProStategy { public: virtual double CalcPro(const Context &ctx) = 0; virtual ~ProStategy(); };
class VAC_Spring : public ProStategy { public: virtual double CalcPro(const Context &ctx){} };
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){} };
class VAC_Wuyi : public ProStategy { public: virtual double CalcPro(const Context &ctx){} };
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; }
|
2024-03-30
该篇文章被 Cleofwine
归为分类:
服务端