当前位置: 首页 > news >正文

【设计模式】创建型设计模式

文章目录

    • 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中的信号其实和日常生活中的信号还是挺像的&#xff0c;LInux中的信号是一种事件通知机制&#xff0c;通知进程发生了某个事件。进程接收到信号后&#xff0c;就会中断当前…...

Vulnhub项目:Web Machine(N7)

靶机地址&#xff1a;Web Machine(N7)渗透过程&#xff1a;kali ip&#xff1a;192.168.56.104&#xff0c;靶机ip&#xff0c;使用arp-scan进行查看靶机地址&#xff1a;192.168.56.128收集靶机开放端口&#xff1a;nmap -sS -sV -T5 -A 192.168.56.128开放了80端口&#xff0…...

Qt基础之三十三:海量网络数据实时显示

开发中我们可能会遇到接收的网络数据来不及显示的问题。最基础的做法是限制UI中加载的数据行数,这样一来可以防止内存一直涨,二来数据刷新非常快,加载再多也来不及看。此时UI能看到数据当前处理到什么阶段就行,实时性更加重要,要做数据分析的话还得查看日志文件。 这里给出…...

linux console快捷键

Ctrl C&#xff1a;终止当前正在运行的程序。Ctrl D&#xff1a;关闭当前终端会话。Ctrl Z&#xff1a;将当前程序放入后台运行。Ctrl L&#xff1a;清除当前屏幕并重新显示命令提示符。Ctrl R&#xff1a;在历史命令中进行逆向搜索。Ctrl A&#xff1a;将光标移动到行首…...

弗洛伊德龟兔赛跑算法(弗洛伊德判圈算法)

弗洛伊德( 罗伯特・弗洛伊德)判圈算法(Floyd Cycle Detection Algorithm)&#xff0c;又称龟兔赛跑算法(Tortoise and Hare Algorithm)&#xff0c;是一个可以在有限状态机、迭代函数或者链表上判断是否存在环&#xff0c;以及判断环的起点与长度的算法。昨晚刷到一个视频&…...

nodejs篇 express(1)

文章目录前言express介绍安装RESTful接口规范express的简单使用一个最简单的服务器&#xff0c;仅仅只需要几行代码便可以实现。restful规范的五种接口类型请求信息req的获取响应信息res的设置中间件的使用自定义中间件解决跨域nodejs相关其它内容前言 express作为nodejs必学的…...

Java实习生------Redis常见面试题汇总(AOF持久化、RDB快照、分布式锁、缓存一致性)⭐⭐⭐

“年轻人&#xff0c;就要勇敢追梦”&#x1f339; 参考资料&#xff1a;图解redis 目录 谈谈你对AOF持久化的理解&#xff1f; redis的三种写回策略是什么&#xff1f; 谈谈你对AOF重写机制的理解&#xff1f;AOF重写机制的具体过程&#xff1f; 谈谈你对RDB快照的理解&a…...

seata服务搭建

它支持两种存储模式&#xff0c;一个是文件&#xff0c;一个是数据库&#xff0c;下面我们分别介绍一下这两种配置nacos存储配置&#xff0c;注意如果registry.conf中注册和配置使用的是file&#xff0c;就会去读取file.config的配置&#xff0c;如果是nacos则通过nacos动态读取…...

Kafka和RabbitMQ有哪些区别,各自适合什么场景?

目录标题1. 消息的顺序2. 消息的匹配3. 消息的超时4. 消息的保持5. 消息的错误处理6. 消息的吞吐量总结1. 消息的顺序 有这样一个需求&#xff1a;当订单状态变化的时候&#xff0c;把订单状态变化的消息发送给所有关心订单变化的系统。 订单会有创建成功、待付款、已支付、已…...

用Pytorch构建一个喵咪识别模型

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 目录 一、前言 二、问题阐述及理论流程 2.1问题阐述 2.2猫咪图片识别原理 三、用PyTorch 实现 3.1PyTorch介绍 3.2PyTorch 构建模型的五要素 3.3PyTorch 实现的步骤 3.3.…...

QT搭建MQTT开发环境

QT搭建MQTT开发环境 第一步、明确安装的QT版本 注意&#xff1a; 从QT5.15.0版本开始&#xff0c;官方不再提供离线版安装包&#xff0c;除非你充钱买商业版。 而在这里我使用的QT版本为5.15.2&#xff0c;在线安装了好久才弄好&#xff0c;还是建议使用离线安装的版本 在这里…...

Python3,5行代码,生成自动排序动图,这操作不比Excel香?

5行代码生成自动排序动图1、引言2、代码实战2.1 pynimate介绍2.2 pynimate安装2.3 代码示例3、总结1、引言 小屌丝&#xff1a;鱼哥&#xff0c;听说你的excel段位又提升了&#xff1f; 小鱼&#xff1a;你这是疑问的语气&#xff1f; 小屌丝&#xff1a;没有~ 吧… 小鱼&…...

【Java SE】变量的本质

目录一. 前言二. 变量(variable)2.1 性质2.2 变量类型2.2.1 核心区别2.3 变量的使用三. 总结一. 前言 一天一个Java小知识点&#xff0c;助力小伙伴更好地入门Java&#xff0c;掌握更深层次的语法。 二. 变量(variable) 2.1 性质 变量本质上就是代表一个”可操作的存储空间”…...

【Android笔记85】Android之使用Camera和MediaRecorder录制视频

这篇文章,主要介绍Android之使用Camera和MediaRecorder录制视频。 目录 一、录制视频 1.1、案例运行效果 1.2、创建Camera对象 1.3、创建MediaRecorder对象...

MySQL集群搭建与高可用性实现:掌握主从复制、多主复制、负载均衡和故障切换技术,让你的MySQL数据库永不宕机!

MySQL集群和高可用性MySQL是一款广泛使用的关系型数据库管理系统&#xff0c;常用于Web应用和企业级应用中。为了提高MySQL的可用性&#xff0c;我们可以通过搭建MySQL集群和实现高可用性来保障数据的稳定性和可靠性。本文将介绍如何搭建MySQL集群和实现高可用性&#xff0c;包…...

收到6家大厂offer,我把问烂了的《Java八股文》打造成3个文档。共1700页!!

前言大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了&#xff0c;考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些程序员了。这不&#…...

多线程 (六) 单例模式

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…...

Docker入门到放弃笔记之容器

1、启动容器1.1容器hello world1.2 容器bash终端1.3 后台运行容器是 Docker 三大核心概念之一&#xff0c;其余两个是镜像与仓库。本文主讲容器。简单的说&#xff0c;容器是独立运行的一个或一组应用&#xff0c;以及它们的运行态环境。对应的&#xff0c;虚拟机可以理解为模拟…...

项目二 任务三 训练5 交换机的HSRP技术

在“项目二 任务三 训练4 交换机的DHCP技术”基础上继续完成下列操作&#xff1a; 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…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...

RabbitMQ 各类交换机

为什么要用交换机&#xff1f; 交换机用来路由消息。如果直发队列&#xff0c;这个消息就被处理消失了&#xff0c;那别的队列也需要这个消息怎么办&#xff1f;那就要用到交换机 交换机类型 1&#xff0c;fanout&#xff1a;广播 特点 广播所有消息​​&#xff1a;将消息…...

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地

NineData 的数据库 DevOps 解决方案已完成对百度智能云向量数据库 VectorDB 的全链路适配&#xff0c;成为国内首批提供 VectorDB 原生操作能力的服务商。此次合作聚焦 AI 开发核心场景&#xff0c;通过标准化 SQL 工作台与细粒度权限管控两大能力&#xff0c;助力企业安全高效…...