【设计模式】创建型设计模式
文章目录
- 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 Principle,OCP):对扩展(组合和继承)开放,对修改关闭
- 单一职责原则(Single Responsibility Principle,SRP):一个类或模块只负责一个功能,即一个类应该仅有一个引起它变化的原因
- 里氏替换原则(Liskov Substitution Principle,LSP):子类可以替换父类,并且保持程序的正确性
- 接口隔离原则(Interface Segregation Principle,ISP):接口应该尽量小而专一,不应该强迫客户依赖于它们不用的方法,避免臃肿和多余;一般用于处理一个类拥有比较多的接口,而这些接口涉及到很多职责
- 面向接口原则(Interface Oriented Principle,IOP):不将变量类型声明为某个特定的具体类,而是声明为某个接口;客户程序无需获知对象的具体类型,只需要知道对象所具有的接口;减少系统中各个部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案
- 依赖倒置原则(Dependence Inversion Principle,DIP):高层模块不应该依赖低层模块,二者都应该依赖抽象;抽象不应该依赖具体实现,具体实现应该依赖于抽象
- 合成复用原则(Composite Reuse Principle,CRP):即组合优于继承原则,优先使用组合或聚合而不是继承来实现复用;继承耦合度高,组合耦合度低
- 封装变化点原则(Package Change Point Principle,PCPP):将稳定点和变化点分离,扩展修改变化点;让稳定点和变化点实现层次分离
- 迪米特法则(Law of Demeter,LoD):一个对象应该尽量少地了解其他对象
前四个设计原则最为重要
3. 模板方法
① 定义
定义一个操作中的算法骨架,而将一些步骤延迟到子类中
Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
②背景
某一个表演有一套特定的展示流程,但是其中有若干个表演子流程可创新替换,宜昌市迭代更新表演流程
③ 要点
- 最常用的设计模式,子类可以复写父类子流程,使弗雷德骨架流程丰富
- 反向控制流程的典型应用
- 父类protected保护子类需要复写的子流程,这样子类的子流程只能父类来调用
④ 本质
通过固定算法骨架来约束子类的行为
⑤ 结构图
⑥ 样例代码
#include <iostream>using 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 <vector>using 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::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;
}
5. 策略模式
① 定义
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换,该模式使得算法可独立于使用它的客户程序而变化
②背景
某商场节假日有固定促销活动,为了加大促销力度,现提升国庆节促销活动规格
③ 要点
- 策略模式提供了一系列可重用的算法,从而可以使得类型在运⾏时方便地根据需要在各个算法之间进行切换
- 策略模式消除了条件判断语句,也就是在解耦合
④ 本质
分离算法,选择实现
⑤ 结构图
⑥ 样例代码
#include <iostream>using 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;
}
补充:
- 析构函数设为虚函数:是为了实现多态性,即当用父类指针删除子类对象时,能够正确地调用子类的析构函数,从而避免内存泄漏或其他错误;如果父类的析构函数不是虚函数,那么只会调用父类的析构函数,导致子类的资源没有被释放
【设计模式】创建型设计模式相关推荐
- 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)
创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...
- 设计模式--创建型设计模式
一. 设计模式的目的 编写软件过程中,可能面临来自耦合性.内聚性.可维护性.可扩展性.重用性.灵活性等多方面的挑战,设计模式是为了让程序具有更好的: 代码重用性(即相同的代码,不用多次编写) 可读 ...
- javaScript设计模式-创建型设计模式
我们大家一听到设计模式就感觉设计模式是一个高端的东西,到底什么是设计模式呢?其实设计模式也就是我们的前辈在写代码的时候遇到的问题,提出的解决方案,为了方便人与人之间的交流,取了个名字,叫做设计模式. ...
- 设计模式——创建型设计模式
创建型设计模式 争对对象/类创建时的优化 工厂方法模式(了解) 通过定义顶层抽象工厂类,通过继承的方式,针对于每一个产品都提供一个工厂类用于创建. 情况:只适用于简单对象,当我们需要生产许多个产品族的 ...
- 设计模式 - 创建型设计模式小结
分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 创建型模式比较简单,但是会比较没有意思,结构型和行为 ...
- 创建型设计模式(待更新)
前言 - 熟能生巧(★★★) 关于设计模式的学习,需要结合具体的应用场景进行理解,即站在用户的角度去理解需求,目的是让自己设计的代码能够为用户提供统一的接口,并且设计的模块具有高内聚低耦合.有更好的可 ...
- JAVA设计模式第二讲:创建型设计模式
设计模式(design pattern)是对软件设计中普遍存在的各种问题,所提出的解决方案.本文以面试题作为切入点,介绍了设计模式的常见问题.我们需要掌握各种设计模式的原理.实现.设计意图和应用场景, ...
- 技术图文:02 创建型设计模式(下)
创建型设计模式(下) 知识结构: 图1 知识结构 单例模式 – 确保对象的唯一性 Sunny 软件公司承接了一个服务器负载均衡软件的开发工作,该软件运行在一台负载均衡服务器上,可以将并发访问和数据流量 ...
- 技术图文:02 创建型设计模式(上)
创建型设计模式(上) 知识结构: 图1 知识结构 简单工厂模式 Sunny 软件公司欲基于 C# 语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图表,如: 柱状图(histogram) ...
- 创建型设计模式对比总结 设计模式(八)
创建型模式是new 的一种替代方式,可以将对象的创建与具体的类型进行分离 目前已经介绍了5种创建型设计模式(如果简单工厂算一种的话,那就是6种) 分别是: 简单工厂模式.工厂方法模式.抽象工厂模式.建 ...
最新文章
- 嵌入式linux dhcp移植,嵌入式linux中的dhcp服务器
- linux使用线程实现生产者消费者问题,Linux平台下线程同步,实现“生产者消费者问题”...
- SqlServer数据类型
- 【知识图谱实战】 Neo4j入门与示例
- Java并发编程的艺术笔记(七)——CountDownLatch、CyclicBarrier详解
- TestBird成为“国家手游测试中心”
- android 仿ios tabs,React Native兼容iOS Android的TabBar
- python去重且顺序不变_Python中list去重且保持原顺序不变的方法
- Music List
- XPath语法及使用
- .NET Core,PostgreSQL和文档数据库
- canvas绘制渐变
- J2Cache的学习
- AquaCrop_原理学习笔记06:土壤水分运动
- word文档保护密码忘 了,怎么取消格式和编辑保护
- 2017第三届美亚杯全国电子数据取证大赛团队赛write up
- 数据通信网的交换方式
- C++生成简单WAV文件(三)——根据简谱生成菊花台
- 趣游CEO玉红:年收入6亿的网页游戏平台缔造者
- Angel Beats,AFOer Beats?