设计模式 - 结构型
结构型
适配器模式,代理模式,桥接模式,装饰器模式,外观模式,组合模式,享元模式,
| 单一职责 | 避免子类爆炸 |
|---|---|
| Bridge 模式 | 对象的实现 |
| Decorator 模式 | 对对象的职责,不生成子类 |
| 接口隔离 | |
| Adapter 模式 | 针对对象的接口 |
| Facade 模式 | 对一个子系统的接口 |
| Proxy 模式 | 如何访问一个对象;该对象的位置 |
| 数据结构 | |
| Composite 模式 | 一个对象的结构和组成 |
| 对象性能 | |
| Flyweight 模式 | 对象的存储开销 |
单一职责(避免子类爆炸)
subclass explode
Bridge 桥接模式
概念
桥接模式和装饰器模式一样,解决因为没有遵循单一职责原则而导致的子类数量爆炸。
-
装饰器模式
-
组合且继承
子类可能会调用其他子类的实现。
-
-
桥接模式
-
组合而不继承。
实现类 不会调用其他子类的实现
-
实现类对应拆分前的子类,实际上由于没有继承,所以这里叫实现类更好。
-
-
核心思想都是一样的,组合优于继承,单一职责。
具体来说:1+n+n*m 个子类,变为 1 纯虚 (+ 1通用实现)+ n iml实现类 + m个应用场景
- 1 纯虚:接口
- n 平台实现Imp
- m 业务抽象(特定平台不同版本) (Imp平台实现作为参数 拼装)
业务抽象不需要继承接口或者平台实现,持有的基类的指针,运行时会指向iml平台实现(实现类)。
- 桥接模式实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。
- 对于两个独立变化的维度,使用桥接模式再适合不过了。
- 分离抽象接口及其实现部分。提高了比继承更好的解决方案
code
bridge.h
#include <cstdio>
#include <iostream>class AbstractionImp {
public:virtual void Operation_RunPythonInTerminal() = 0;
};// ConcreteAbstractionImp
class ConcreteAbstractionImp_Python2 : public AbstractionImp {
public:void Operation_RunPythonInTerminal() {printf("start python2 \n");}
};class ConcreteAbstractionImp_Python3 : public AbstractionImp {
public:void Operation_RunPythonInTerminal() {printf("start python3 \n");}
};
bridge.cpp
#include "bridge_Imp.h"
// class AbstractionImp;class Abstraction {
public:AbstractionImp* mImp = nullptr;virtual void Operation_RunPythonInTerminal() = 0;
};class RefinedAbstraction_Windows : public Abstraction{
public:void Operation_RunPythonInTerminal() {printf("windows start WSL\n");if (mImp)mImp->Operation_RunPythonInTerminal();}
};class RefinedAbstraction_Linux : public Abstraction{
public:void Operation_RunPythonInTerminal() {printf("linux start cmd\n");if (mImp)mImp->Operation_RunPythonInTerminal();}
};int main() {Abstraction* mOS = new RefinedAbstraction_Windows;AbstractionImp* mPython = new ConcreteAbstractionImp_Python3;mOS->mImp = mPython;mOS->Operation_RunPythonInTerminal();free(mPython);mPython = new ConcreteAbstractionImp_Python2;mOS->mImp = mPython;mOS->Operation_RunPythonInTerminal();free(mPython);free(mOS);return 0;
}
Decorator 装饰器
概念
单一职责,避免了子类的无限制膨胀,消除重复代码,兼具开闭选择。
-
特征
-
子类继承基类
多继承,多子类衍生 时的一个解决方法
-
子类持有基类的指针。
根据里氏替换,可以调用基类的同名方法,并在前后加上子类的操作。组合优于继承。
-
-
应用于 主体类多个方向上的扩展功能
-
主体操作和扩展操作,应该分开分支继承。
-
扩展操作通过持有的主体操作的指针,造成附加动作之后 调用主体操作。
-
code
#include <cstdio>
#include <iostream>
#include <iostream>
#include <string>class DecoratorBase {
public:DecoratorBase* mImp = nullptr;virtual void Operation() = 0;
};class ImpParty : public DecoratorBase {
public:std::string bro = "";ImpParty(std::string bro) {this->bro = bro;}void setBro(std::string name) {this->bro = name;}void Operation() {printf("Party start, hi %s\n", bro.c_str());if (mImp) {printf("lets drink!\n");mImp->Operation();}}
};class ImpSoftDrink : public DecoratorBase {
public:std::string softdrink = "";ImpSoftDrink(std::string softdrink) {this->softdrink = softdrink;}void Operation() {printf("lets drink %s", softdrink.c_str());}
};int main() {ImpParty* mParty = new ImpParty("John");ImpSoftDrink* mDrink = new ImpSoftDrink("cola");mParty->mImp = mDrink;mParty->Operation();delete mDrink;delete mParty;return 0;
}
数据结构
composite 组合模式
概念
将对象组合成树状结构,树形结构不暴露给外界。
Compoment
树节点 composite 子类
-
持有 一个子类的链表
-
add remove方法修改 其中的子类的链表
-
process方法,执行子类链表中所有子类的process函数。直到叶子节点
叶子节点 leaf 没有链表,process函数执行功能。
接口隔离
其它人的代码
Adoptor 适配器模式
概念
为了完成某项工作购买了一个第三方的库来加快开发。这就带来了一个问题:我们在应用程序中已经设计好了接口,与这个第三方提供的接口不一致,为了使得这些接口不兼容的类(不能在一起工作)可以在一起工作了,Adapter 模式提供了将一个类(第三方库)的接口转化希望的接口。
Itarget新实现的接口。adapter新实现。adaptee被适配的旧类
适配器模式分为类模式和对象模式。
-
常用做法。对象模式:对象适配器 adapter,采用组合原有接口类的方式
-
持有adaptee,组合用于实现。
-
public继承Itarget 接口。
-
-
不常用做法。类模式:类适配器 adapter,采用继承原有接口类的方式
-
protect继承adaptee,用于实现。
-
public继承Itarget接口。(不灵活 继承的方案不灵活 类的多继承在cpp之外的语言压根就不支持)
-
code 继承
#include <cstdio>
class Target_rob {
public:virtual int giveMeYrMoney() = 0;
};class Adaptee_robInFrance {
public:int doRob() {printf("Levez les mains, donnez moi votre argent!\n");return 1000;}
};class Adaptor_rob : public Target_rob, Adaptee_robInFrance {
public:int giveMeYrMoney() {return doRob();}
};int main() {Target_rob* mClinet = dynamic_cast<Target_rob*>(new Adaptor_rob());int money = mClinet->giveMeYrMoney();printf("we got %d RMB!", money);
}
code 组合
#include <cstdio>
#include <cstdlib>
class Adaptee_rob {
public:virtual int doRob() = 0;
};
class Adaptee_robInFrance : public Adaptee_rob {
public:int doRob() {printf("Levez les mains, donnez moi votre argent!\n");return 1000;}
};class Target_rob {
public:Adaptee_rob* mAdaptee = nullptr;virtual int giveMeYrMoney() = 0;
};class Adaptor_rob : public Target_rob {
public:int giveMeYrMoney() {int money = 0;if (mAdaptee) {money = mAdaptee->doRob();} else {printf("we got nothing \n");}return money;}
};int main() {Target_rob* mClinet = dynamic_cast<Target_rob*>(new Adaptor_rob());Adaptee_rob* mRobber = dynamic_cast<Adaptee_rob*>(new Adaptee_robInFrance());mClinet->mAdaptee = mRobber;int money = mClinet->giveMeYrMoney();printf("we got %d RMB!", money);return 0;
}
facade 门面模式
facad 门面模式 解欧系统见的交互
框架层面,没有具体的实例代码。对内 高内聚 对外应该松耦合。
封装内部可能高度复杂 高度耦合的盒子。例如安卓的vendor hal。数据访问相关sql等等。
Proxy 代理模式
在不失去透明操作对象的同时,控制管理这些对象内部特有的复杂性
对其他对象特供一种代理,以控制 (隔离 使用接口)对这个接口的访问。
- 对象创建开销大
- 某些操作需要安全控制
- 需要进程外的访问(分布式等)
对象性能
Flyweight 享元模式
内存池,每个字的字体,单例模式从容器中取出。
实现 右值引用 复制,clone原型模式
––– 接口隔离 –––
- List item
相关文章:
设计模式 - 结构型
结构型 适配器模式,代理模式,桥接模式,装饰器模式,外观模式,组合模式,享元模式, 单一职责避免子类爆炸Bridge 模式对象的实现Decorator 模式对对象的职责,不生成子类接口隔离Adapt…...
STM32编码器接口
一、概述 1、Encoder Interface 编码器接口概念 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度每个高级定时器和通用…...
2024客户世界年度大会开幕,码号卫士赋能数字运营服务新升级
10月15日,2024年客户世界年度的大会在通州北投希尔顿酒店开幕。作为行业内的一个重要活动,本次大会以“数字运营支撑服务产业新升级”为主题,吸引了众多行业专家和企业代表。 据悉,本次大会以“数字运营支撑服务产业新升级”为主题…...
AcWing 802. 区间和(离散化算法,python)
本篇博客详细讲解一下离散化知识点,通过讲解和详细列题带大家掌握离散化。 题目: 原题链接:https://www.acwing.com/problem/content/description/804/ 假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。 现在,…...
【网页设计】CSS 盒子模型
目标 能够准确阐述盒子模型的 4 个组成部分能够利用边框复合写法给元素添加边框能够计算盒子的实际大小能够利用盒子模型布局模块案例能够给盒子设置圆角边框能够给盒子添加阴影能够给文字添加阴影 1. 盒子模型 页面布局要学习三大核心, 盒子模型, 浮动 和 定位. 学习好盒子模…...
如何通过构建对应的api服务器使Vue连接到数据库
一、安装数据库驱动 在后端安装 MySQL 数据库驱动,比如在 Node.js 环境中可以使用 mysql2 包来连接 MySQL 数据库。在项目目录下运行以下命令安装: npm install mysql2或者使用 yarn: yarn add mysql2二、创建数据库连接模块 创建一个专门…...
新手给视频加字幕的方法有哪些?4种加字幕方法推荐!
在视频制作中,字幕不仅是传递信息的重要手段,还能增强视频的观感和专业性。对于新手来说,如何给视频添加字幕可能是一个挑战。本文将介绍字幕的类型、推荐添加字幕的工具,以及详细添加字幕方法,帮助新手轻松掌握视频字…...
Oracle实际需要用到但常常被忽略的函数
1、Oracle中nvl()与nvl2()函数 函数nvl(expression1,expression2)根据参数1是否为null返回参数1或参数2的值; 函数nvl2(expression1,expression2,expression3)根据参数1是否为null返回参数2或参数3的值 【函数格式】:nvl(expression1,expression2) 若…...
代码随想录算法训练营Day23
局部最优——>全局最优&无反例,试试贪心 455.分发饼干 力扣题目链接:. - 力扣(LeetCode) class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(s);Arrays.sort(g);int gindex0;int count0;…...
vue使用table实现动态数据报表(行合并)
<template><div class"previewTable"><h2>***项目研发数据报告</h2><table id"previewTable" width"100%"><tr><th>项目名称</th><td colspan"6">{{ resultData.proName }}<…...
YARN调度原理详解
YARN(Yet Another Resource Negotiator)是 Hadoop 集群的资源管理和作业调度框架,它的设计旨在更好地管理和调度 Hadoop 集群中的资源。YARN 解决了传统 Hadoop MapReduce 中资源管理与作业调度紧耦合的问题,使得不同类型的计算任…...
Go-知识泛型
Go-知识泛型 1. 认识泛型1.1 不使用泛型1.2 使用泛型 2. 泛型的特点2.1 函数泛化2.2 类型泛化 3. 类型约束3.1 类型集合3.2 interface 类型集合3.2.1 内置interface类型集合3.2.2 自定义interface类型集合3.2.2.1 任意类型元素3.2.2.2 近似类型元素3.2.2.3 联合类型元素 3.2.3 …...
Qt 如何 发送与解析不定长报文以及数组不定长报文
文章目录 割方式一,采用QDataStream 解析,可直接设定大小端解析,无需自己转换方式二,采用结构体字节对齐方式解析发送接收方割 方式一,采用QDataStream 解析,可直接设定大小端解析,无需自己转换 需要注意的是结构体定义要去掉字节对齐,否则会崩溃,因为由自定义数据结…...
Rust默认使用UTF-8编码来解析源代码文件。如果在代码中包含无法用UTF-8编码表示的字符,编译器会报错!
文章目录 Rust默认编码示例在ANSI编码下中文显示正常的代码在UTF-8编码下将显示不正常在编译时,Rust使用UTF-8编码来解析代码,发现无法用UTF-8编码表示的字符,于是编译器报错 Rust默认编码 Rust 语言默认使用 UTF-8 编码来解析源代码文件。如…...
【jeston】torch相关环境安装
参考:玩转NVIDIA Jetson (25)— jetson 安装pytorch和torchvision 我的jeston信息: torch install 安装环境 conda create -n your_env python3.8 conda activate your_envpytorch_for_jeston 安装.whl文件 验证࿱…...
[CR]厚云填补_大型卫星影像去云数据集
AllClear: A Comprehensive Dataset and Benchmark for Cloud Removal in Satellite Imagery Abstract 卫星图像中的云对下游应用构成了重大挑战。当前云移除研究的一个主要挑战是缺乏一个全面的基准和一个足够大和多样化的训练数据集。为了解决这个问题,我们引入了…...
Langchain CharacterTextSplitter无法分割文档问题
在使用Langchain的文档分割器时,使用CharacterTextSplitter拆分文档是,发现返回的文档根本没有变化,即使设置了chunk_size,返回的大小也不符合参数设置。 CharacterTextSplitter设置了150,但是根本没有处理࿰…...
ros service不走是为什么
在ROS(Robot Operating System)中,如果ROS服务(Service)没有正常工作,可能有多种原因。你可以检查以下几点来排查问题: 服务是否正确启动 首先,确保服务节点已经启动并注册了相应的…...
量子计算机的原理与物理实现
量子计算机的原理与物理实现很复杂 指导性原则 首先思考制备一台量子计算机需要些什么? 需要量子比特——二能级量子系统。除了量子计算机需要满足一些物理特性,它还必须要把量子比特绘制到某种初态上,以及测量系统的输出态。 而实验上的挑战…...
SQL Server 常用关键词语法汇总
一、函数 1.1 CAST CAST ( expression AS data_type [ ( length ) ] )expression: 这是你想要转换的数据或表达式。data_type: 目标数据类型,比如 INT, VARCHAR, DATE 等等。(length): 对于某些数据类型(如 CHAR, VARCHAR, BINARY, VARBINARYÿ…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
