同仁微网站建设工作室,做跨境的网站,网站开发获客渠道,天津建站平台文章目录1. 基础①如何学习设计模式② 类模型③ 类关系2. 设计原则3. 模板方法① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码4. 观察者模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码5. 策略模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码1. 基础
①如何学习…
文章目录1. 基础①如何学习设计模式② 类模型③ 类关系2. 设计原则3. 模板方法① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码4. 观察者模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码5. 策略模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码1. 基础
①如何学习设计模式
找稳定点和变化点把变化点隔离出来解耦合先满足设计原则慢慢迭代出设计模式抽象思维、分治思维
② 类模型 ③ 类关系 Stranger可以访问TonyFather中的public成员变量TonyFather可以访问TonyFather中的public、protected成员变量Beauty可以访问TonyFather中的public、protected以及private成员变量但是TonyFather是无法访问Beauty中的protected和private成员变量的因为友元是单向的TonyMother与访问TonyFather可以互相访问对方的所有成员变量因为两者都声明对方为友元
2. 设计原则
开放封闭原则Open Closed PrincipleOCP对扩展组合和继承开放对修改关闭单一职责原则Single Responsibility PrincipleSRP一个类或模块只负责一个功能即一个类应该仅有一个引起它变化的原因里氏替换原则Liskov Substitution PrincipleLSP子类可以替换父类并且保持程序的正确性接口隔离原则Interface Segregation PrincipleISP接口应该尽量小而专一不应该强迫客户依赖于它们不用的方法避免臃肿和多余一般用于处理一个类拥有比较多的接口而这些接口涉及到很多职责面向接口原则Interface Oriented PrincipleIOP不将变量类型声明为某个特定的具体类而是声明为某个接口客户程序无需获知对象的具体类型只需要知道对象所具有的接口减少系统中各个部分的依赖关系从而实现“高内聚、松耦合”的类型设计方案依赖倒置原则Dependence Inversion PrincipleDIP高层模块不应该依赖低层模块二者都应该依赖抽象抽象不应该依赖具体实现具体实现应该依赖于抽象合成复用原则Composite Reuse PrincipleCRP即组合优于继承原则优先使用组合或聚合而不是继承来实现复用继承耦合度高组合耦合度低封装变化点原则Package Change Point PrinciplePCPP将稳定点和变化点分离扩展修改变化点让稳定点和变化点实现层次分离迪米特法则Law of DemeterLoD一个对象应该尽量少地了解其他对象
前四个设计原则最为重要
3. 模板方法
① 定义
定义一个操作中的算法骨架而将一些步骤延迟到子类中
Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
②背景
某一个表演有一套特定的展示流程但是其中有若干个表演子流程可创新替换宜昌市迭代更新表演流程
③ 要点
最常用的设计模式子类可以复写父类子流程使弗雷德骨架流程丰富反向控制流程的典型应用父类protected保护子类需要复写的子流程这样子类的子流程只能父类来调用
④ 本质
通过固定算法骨架来约束子类的行为
⑤ 结构图 ⑥ 样例代码
#include iostreamusing namespace std;class Perform {
public:void show() {if (show0())playGame();show1();show2();show3();}private:void playGame() {cout show0 end, have a small game endl;}protected:virtual bool show0() {cout show0 endl;return true;}virtual void show1() {}virtual void show2() {cout show2 endl;}virtual void show3() {}
};class PerformEx1 : public Perform {
protected:virtual bool show0() {cout ex1 show0 endl;return true;}virtual void show2() {cout ex1 show2 endl;}
};class PerformEx2 : public Perform {
protected:virtual void show1() {cout ex2 show1 endl;}virtual void show2() {cout ex2 show2 endl;}
};class PerformEx3 : public Perform {
protected:virtual void show1() {cout ex3 show1 endl;}virtual void show2() {cout ex3 show2 endl;}virtual void show3() {cout ex3 show3 endl;}
};int main()
{Perform *p1 new PerformEx1();p1-show();cout endl;Perform *p2 new PerformEx2();p2-show();cout endl;Perform *p3 new PerformEx3();p3-show();cout endl;return 0;
}补充
protected修饰符修饰类的成员可以被同一个类中的其他成员函数访问也可以被派生类中的成员函数访问但不能被其他地方访问protected修饰符适用于继承关系中保护基类的成员不被外部修改但允许派生类修改virtual关键字的作用是用来定义虚函数实现动态绑定。虚函数是指在基类中声明为virtual的成员函数它可以在派生类中被重写当通过基类类型的指针或引用调用虚函数时会根据对象的实际类型调用相应的重写版本virtual关键字也可以用于虚继承避免多重继承时出现菱形继承问题virtual function() 0的作用是定义纯虚函数。纯虚函数是一种没有实现的虚函数它只有声明没有定义纯虚函数的目的是让派生类去重写它实现多态如果一个类中有纯虚函数那么这个类就是抽象类不能被实例化
4. 观察者模式
① 定义
定义对象间的一种一对多变化的依赖关系以便当一个对象subject的状态发生改变时所有依赖于它的对象都得到通知并自动更新
②背景
气象站发布气象资料给数据中心数据中心经过处理将气象信息更新到不同的显示终端上
③ 要点
观察者模式使得我们可以独立地改变目标与观察者从而使二者之间的关系松耦合观察者自己决定是否订阅通知目标对象并不关注谁订阅了观察者不要依赖通知顺序目标对象也不知道通知顺序常用在基于事件的ui框架中也是MVC的组成部分常用在分布式系统和actor框架中zk、etcd、kafka、redis、分布式锁
④ 本质
触发联动
⑤ 结构图 ⑥ 样例代码
#include iostream
#include vectorusing namespace std;class IDisplay
{
public:virtual void show(float temperature) 0;virtual ~IDisplay() {}
};class DisplayA : public IDisplay
{
public:virtual void show(float temperature);private:void ownFunction(); // 可以在子类上继续添加自己需要的函数
};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:bool attach(IDisplay *ob);bool detach(IDisplay *ob);void notify(){float temperature CalcTemperature();for (auto iter this-obs.begin(); iter ! obs.end(); iter)(*iter)-show(temperature);}
private:virtual WeatherData *GetWeatherData();virtual float CalcTemperature(){WeatherData *data GetWeatherData();// ...float temperature;return temperature;}std::vectorIDisplay * 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;
}5. 策略模式
① 定义
定义一系列算法把它们一个个封装起来并且使它们可互相替换该模式使得算法可独立于使用它的客户程序而变化
②背景
某商场节假日有固定促销活动为了加大促销力度现提升国庆节促销活动规格
③ 要点
策略模式提供了一系列可重用的算法从而可以使得类型在运⾏时方便地根据需要在各个算法之间进行切换策略模式消除了条件判断语句也就是在解耦合
④ 本质
分离算法选择实现
⑤ 结构图 ⑥ 样例代码
#include iostreamusing namespace std;class Context
{// 环境类
};class ProStrategy
{// 抽象的策略类
public:// 算法接口virtual double CalcPro(const Context ctx) 0;virtual ~ProStrategy();
};// 派生出的具体策略类
class VAC_Spring : public ProStrategy {
public:virtual double CalcPro(const Context ctx){}
};class VAC_Labor : public ProStrategy {
public:virtual double CalcPro(const Context ctx){}
};
class VAC_Labor1 : public VAC_Labor {
public:virtual double CalcPro(const Context ctx){}
};class VAC_National : public ProStrategy {
public:virtual double CalcPro(const Context ctx){}
};class VAC_Christmas : public ProStrategy {
public:virtual double CalcPro(const Context ctx){}
};class Promotion
{
public:Promotion(ProStrategy *s) : s(s){}~Promotion(){}double CalcPromotion(const Context ctx) {return s-CalcPro(ctx);}
private:ProStrategy *s;
};int main()
{Context ctx;ProStrategy *s new VAC_Labor1();Promotion *p new Promotion(s);p-CalcPromotion(ctx);return 0;
}补充
析构函数设为虚函数是为了实现多态性即当用父类指针删除子类对象时能够正确地调用子类的析构函数从而避免内存泄漏或其他错误如果父类的析构函数不是虚函数那么只会调用父类的析构函数导致子类的资源没有被释放