【设计模式】创建型设计模式
文章目录
- 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;
}
补充:
- 析构函数设为虚函数:是为了实现多态性,即当用父类指针删除子类对象时,能够正确地调用子类的析构函数,从而避免内存泄漏或其他错误;如果父类的析构函数不是虚函数,那么只会调用父类的析构函数,导致子类的资源没有被释放
相关文章:
【设计模式】创建型设计模式
文章目录1. 基础①如何学习设计模式② 类模型③ 类关系2. 设计原则3. 模板方法① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码4. 观察者模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码5. 策略模式① 定义②背景③ 要点④ 本质⑤ 结构图⑥ 样例代码1. 基础 ①如何学习…...
Linux 信号(signal):信号的理解
目录一、理解信号1.信号是什么2.信号的种类二、简单理解信号的生命周期一、理解信号 1.信号是什么 Linux中的信号其实和日常生活中的信号还是挺像的,LInux中的信号是一种事件通知机制,通知进程发生了某个事件。进程接收到信号后,就会中断当前…...
Vulnhub项目:Web Machine(N7)
靶机地址:Web Machine(N7)渗透过程:kali ip:192.168.56.104,靶机ip,使用arp-scan进行查看靶机地址:192.168.56.128收集靶机开放端口:nmap -sS -sV -T5 -A 192.168.56.128开放了80端口࿰…...
Qt基础之三十三:海量网络数据实时显示
开发中我们可能会遇到接收的网络数据来不及显示的问题。最基础的做法是限制UI中加载的数据行数,这样一来可以防止内存一直涨,二来数据刷新非常快,加载再多也来不及看。此时UI能看到数据当前处理到什么阶段就行,实时性更加重要,要做数据分析的话还得查看日志文件。 这里给出…...
linux console快捷键
Ctrl C:终止当前正在运行的程序。Ctrl D:关闭当前终端会话。Ctrl Z:将当前程序放入后台运行。Ctrl L:清除当前屏幕并重新显示命令提示符。Ctrl R:在历史命令中进行逆向搜索。Ctrl A:将光标移动到行首…...
弗洛伊德龟兔赛跑算法(弗洛伊德判圈算法)
弗洛伊德( 罗伯特・弗洛伊德)判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm),是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,以及判断环的起点与长度的算法。昨晚刷到一个视频&…...
nodejs篇 express(1)
文章目录前言express介绍安装RESTful接口规范express的简单使用一个最简单的服务器,仅仅只需要几行代码便可以实现。restful规范的五种接口类型请求信息req的获取响应信息res的设置中间件的使用自定义中间件解决跨域nodejs相关其它内容前言 express作为nodejs必学的…...
Java实习生------Redis常见面试题汇总(AOF持久化、RDB快照、分布式锁、缓存一致性)⭐⭐⭐
“年轻人,就要勇敢追梦”🌹 参考资料:图解redis 目录 谈谈你对AOF持久化的理解? redis的三种写回策略是什么? 谈谈你对AOF重写机制的理解?AOF重写机制的具体过程? 谈谈你对RDB快照的理解&a…...
seata服务搭建
它支持两种存储模式,一个是文件,一个是数据库,下面我们分别介绍一下这两种配置nacos存储配置,注意如果registry.conf中注册和配置使用的是file,就会去读取file.config的配置,如果是nacos则通过nacos动态读取…...
Kafka和RabbitMQ有哪些区别,各自适合什么场景?
目录标题1. 消息的顺序2. 消息的匹配3. 消息的超时4. 消息的保持5. 消息的错误处理6. 消息的吞吐量总结1. 消息的顺序 有这样一个需求:当订单状态变化的时候,把订单状态变化的消息发送给所有关心订单变化的系统。 订单会有创建成功、待付款、已支付、已…...
用Pytorch构建一个喵咪识别模型
本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 目录 一、前言 二、问题阐述及理论流程 2.1问题阐述 2.2猫咪图片识别原理 三、用PyTorch 实现 3.1PyTorch介绍 3.2PyTorch 构建模型的五要素 3.3PyTorch 实现的步骤 3.3.…...
QT搭建MQTT开发环境
QT搭建MQTT开发环境 第一步、明确安装的QT版本 注意: 从QT5.15.0版本开始,官方不再提供离线版安装包,除非你充钱买商业版。 而在这里我使用的QT版本为5.15.2,在线安装了好久才弄好,还是建议使用离线安装的版本 在这里…...
Python3,5行代码,生成自动排序动图,这操作不比Excel香?
5行代码生成自动排序动图1、引言2、代码实战2.1 pynimate介绍2.2 pynimate安装2.3 代码示例3、总结1、引言 小屌丝:鱼哥,听说你的excel段位又提升了? 小鱼:你这是疑问的语气? 小屌丝:没有~ 吧… 小鱼&…...
【Java SE】变量的本质
目录一. 前言二. 变量(variable)2.1 性质2.2 变量类型2.2.1 核心区别2.3 变量的使用三. 总结一. 前言 一天一个Java小知识点,助力小伙伴更好地入门Java,掌握更深层次的语法。 二. 变量(variable) 2.1 性质 变量本质上就是代表一个”可操作的存储空间”…...
【Android笔记85】Android之使用Camera和MediaRecorder录制视频
这篇文章,主要介绍Android之使用Camera和MediaRecorder录制视频。 目录 一、录制视频 1.1、案例运行效果 1.2、创建Camera对象 1.3、创建MediaRecorder对象...
MySQL集群搭建与高可用性实现:掌握主从复制、多主复制、负载均衡和故障切换技术,让你的MySQL数据库永不宕机!
MySQL集群和高可用性MySQL是一款广泛使用的关系型数据库管理系统,常用于Web应用和企业级应用中。为了提高MySQL的可用性,我们可以通过搭建MySQL集群和实现高可用性来保障数据的稳定性和可靠性。本文将介绍如何搭建MySQL集群和实现高可用性,包…...
收到6家大厂offer,我把问烂了的《Java八股文》打造成3个文档。共1700页!!
前言大家好,最近有不少小伙伴在后台留言,近期的面试越来越难了,要背的八股文越来越多了,考察得越来越细,越来越底层,明摆着就是想让我们徒手造航母嘛!实在是太为难我们这些程序员了。这不&#…...
多线程 (六) 单例模式
🎉🎉🎉点进来你就是我的人了 博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔🦾&am…...
Docker入门到放弃笔记之容器
1、启动容器1.1容器hello world1.2 容器bash终端1.3 后台运行容器是 Docker 三大核心概念之一,其余两个是镜像与仓库。本文主讲容器。简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟…...
项目二 任务三 训练5 交换机的HSRP技术
在“项目二 任务三 训练4 交换机的DHCP技术”基础上继续完成下列操作: 1、二层交换机50-2的配置 50-2>en 50-2#conf t Enter configuration commands, one per line. End with CNTL/Z. 50-2(config)#int 50-2(config)#interface g 50-2(config)#interface gigab…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
