【设计模式】创建型设计模式
文章目录
- 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…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

C++课设:实现本地留言板系统(支持留言、搜索、标签、加密等)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、项目功能概览与亮点分析1. 核心功能…...