目录

  • “单一职责”模式
    • 装饰器模式 Decorator
      • 引例
      • 动机 Motivation
      • 模式定义
      • 结构 Structure
      • 要点总结

“单一职责”模式

  • 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
  • 典型目录
    • 装饰器模式 Decorator
    • 桥接模式 Bridge

装饰器模式 Decorator

引例

  1. 对于流操作,诸如文件流、网络流、内存流等,分别对其进行诸如加密、缓存等单个或组合的操作,子类庞大。
    // 业务操作
    class Stream
    {
    public:virtual char Read(int number) = 0;virtual char Seek(int position) = 0;virtual char Write(char data) = 0;virtual ~Stream(){}
    };// 主体类
    // 文件流
    class FileStream : public Stream
    {
    public:virtual char Read(int number){// 读文件流}virtual char Seek(int position){// 定位文件流}virtual char Write(char data){// 写文件流}
    };
    // 网络流
    class NetworkStream : public Stream
    {
    public:virtual char Read(int number){// 读网络流}virtual char Seek(int position){// 定位网络流}virtual char Write(char data){// 写网络流}
    };
    // 内存流
    class MemoryStream : public Stream
    {
    public:virtual char Read(int number){// 读内存流}virtual char Seek(int position){// 定位内存流}virtual char Write(char data){// 写内存流}
    };//扩展操作,如加密、缓存、加密缓存
    // 加密文件流
    class CryptoFileStream : public FileStream
    {
    public:virtual char Read(int number){// 额外的加密操作FileStream::Read(number);	// 读文件流,这种为静态特质		}virtual char Seek(int position){// 额外的加密操作FileStream::Seek(position);	// 定位文件流}virtual char Write(char data){// 额外的加密操作FileStream::write(data);// 写文件流}
    };
    // 加密网络流
    class CryptoNetworkStream : public NetworkStream 
    {
    public:virtual char Read(int number){// 额外的加密操作NetworkStream ::Read(number);	// 读网络流		}virtual char Seek(int position){// 额外的加密操作NetworkStream ::Seek(position);	// 定位网络流}virtual char Write(char data){// 额外的加密操作NetworkStream ::write(data);// 写网络流}
    };// 缓存文件流
    class BufferedFileStream : public FileStream
    {
    public:virtual char Read(int number){// 额外的缓存操作FileStream::Read(number);	// 读文件流		}virtual char Seek(int position){// 额外的缓存操作FileStream::Seek(position);	// 定位文件流}virtual char Write(char data){// 额外的缓存操作FileStream::write(data);// 写文件流}
    };
    // 缓存网络流
    class BufferedNetworkStream : public NetworkStream 
    {
    public:virtual char Read(int number){// 额外的缓存操作NetworkStream ::Read(number);	// 读网络流		}virtual char Seek(int position){// 额外的缓存操作NetworkStream ::Seek(position);	// 定位网络流}virtual char Write(char data){// 额外的缓存操作NetworkStream ::write(data);// 写网络流}
    };// 加密缓存文件流
    class CryptoBufferedFileStream : public FileStream
    {
    public:virtual char Read(int number){// 额外的加密操作// 额外的缓存操作FileStream::Read(number);	// 读文件流		}virtual char Seek(int position){// 额外的加密操作// 额外的缓存操作FileStream::Seek(position);	// 定位文件流}virtual char Write(char data){// 额外的加密操作// 额外的缓存操作FileStream::write(data);// 写文件流}
    };
    // 加密网络流
    class CryptoBufferedNetworkStream : public NetworkStream 
    {
    public:virtual char Read(int number){// 额外的加密操作// 额外的缓存操作NetworkStream ::Read(number);	// 读网络流		}virtual char Seek(int position){// 额外的加密操作// 额外的缓存操作NetworkStream ::Seek(position);	// 定位网络流}virtual char Write(char data){// 额外的加密操作// 额外的缓存操作NetworkStream ::write(data);// 写网络流}
    };void Process()
    {// 编译时装配CryptoFileStream *cfs1 = new CryptoFileStream();BufferedFileStream* bfs1 = new BufferedFileStream();CryptoBufferedFileStream* cbfs1 = new CryptoBufferedFileStream();
    }
    

在这里插入图片描述
如第二层m种变化类型,第三层n种变化类型,类的个数 :1+ m + m * n!/ 2

  1. 对第一版代码进行重构

    // 业务操作
    class Stream
    {
    public:virtual char Read(int number) = 0;virtual char Seek(int position) = 0;virtual char Write(char data) = 0;virtual ~Stream(){}
    };// 主体类
    // 文件流
    class FileStream : public Stream
    {
    public:virtual char Read(int number){// 读文件流}virtual char Seek(int position){// 定位文件流}virtual char Write(char data){// 写文件流}
    };
    // 网络流
    class NetworkStream : public Stream
    {
    public:virtual char Read(int number){// 读网络流}virtual char Seek(int position){// 定位网络流}virtual char Write(char data){// 写网络流}
    };
    // 内存流
    class MemoryStream : public Stream
    {
    public:virtual char Read(int number){// 读内存流}virtual char Seek(int position){// 定位内存流}virtual char Write(char data){// 写内存流}
    };//扩展操作,如加密、缓存、加密缓存
    // 加密文件流
    class CryptoStream : public Stream
    {// FileStream* stream; 不必现在确定类型Stream* stream;// = new FileStream(); 未来确实,即运行时确定
    public:CryptoStream(Stream* st) : stream(st){}virtual char Read(int number){// 额外的加密操作stream->Read(number);	// 读流		}virtual char Seek(int position){// 额外的加密操作stream->Seek(position);	// 定位流}virtual char Write(char data){// 额外的加密操作stream->write(data);// 写流}
    };
    // 加密网络流
    class CryptoNetworkStream : public Stream 
    {// NetworkStream * stream; 不必现在确定类型Stream* stream;// = new NetworkStream (); 未来确实,即运行时确定virtual char Read(int number){// 额外的加密操作stream->Read(number);	// 读网络流		}virtual char Seek(int position){// 额外的加密操作stream->Seek(position);	// 定位网络流}virtual char Write(char data){// 额外的加密操作stream->write(data);// 写网络流}
    };
    // 加密文件流/网络流,合并为加密流CryptoStream,结构如下方缓存流// 缓存流
    class BufferedStream : public Stream
    {Stream* stream;
    public:BufferedStream(Stream* st) : stream(st){}virtual char Read(int number){// 额外的加密操作stream->Read(number);	// 读流		}virtual char Seek(int position){// 额外的加密操作stream->Seek(position);	// 定位流}virtual char Write(char data){// 额外的加密操作stream->write(data);// 写流}
    };void Process()
    {// BufferedFileStream* bfs1 = new BufferedFileStream();	// 代码1// CryptoBufferedFileStream* cbfs1 = new CryptoBufferedFileStream();	// 代码1// 运行时装配FileStream* fs1 = new FileSteam();CryptoStream* cfs1 = new CryptoStream(fs1);BufferedStream* bfs1 = new BufferedStream(fs1);CryptoStream* cbfs1 = new CryptoStream(bfs1);}
    
  2. 对第二部分代码,继续重构,将共有部分加入到装饰类:DecoratorStream

    // 业务操作
    class Stream
    {
    public:virtual char Read(int number) = 0;virtual char Seek(int position) = 0;virtual char Write(char data) = 0;virtual ~Stream(){}
    };// 主体类
    // 文件流
    class FileStream : public Stream
    {
    public:virtual char Read(int number){// 读文件流}virtual char Seek(int position){// 定位文件流}virtual char Write(char data){// 写文件流}
    };
    // 网络流
    class NetworkStream : public Stream
    {
    public:virtual char Read(int number){// 读网络流}virtual char Seek(int position){// 定位网络流}virtual char Write(char data){// 写网络流}
    };
    // 内存流
    class MemoryStream : public Stream
    {
    public:virtual char Read(int number){// 读内存流}virtual char Seek(int position){// 定位内存流}virtual char Write(char data){// 写内存流}
    };//扩展操作,如加密、缓存、加密缓存
    DecoratorStream : public Stream
    {
    protected:Stream* stream;DecoratorStream(Stream* st) : stream(st){}
    }// 加密文件流
    class CryptoStream : public DecoratorStream
    {
    public:CryptoStream(Stream* st) : DecoratorStream(st){}virtual char Read(int number){// 额外的加密操作stream->Read(number);	// 读流		}virtual char Seek(int position){// 额外的加密操作stream->Seek(position);	// 定位流}virtual char Write(char data){// 额外的加密操作stream->write(data);// 写流}
    };// 缓存流
    class BufferedStream : public DecoratorStream
    {
    public:BufferedStream(Stream* st) : stream(st){}virtual char Read(int number){// 额外的加密操作stream->Read(number);	// 读流		}virtual char Seek(int position){// 额外的加密操作stream->Seek(position);	// 定位流}virtual char Write(char data){// 额外的加密操作stream->write(data);// 写流}
    };void Process()
    {// 运行时装配FileStream* fs1 = new FileSteam();CryptoStream* cfs1 = new CryptoStream(fs1);BufferedStream* bfs1 = new BufferedStream(fs1);CryptoStream* cbfs1 = new CryptoStream(bfs1);}
    

在这里插入图片描述
类的个数: 1 + m + 1 + n,使用组合(装饰器类中含有被修饰类的指针),来减少类的数量。

动机 Motivation

  • 在某些情况下,我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。

模式定义

动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码及减少子类个数)。

结构 Structure

在这里插入图片描述
红色为稳定部分,蓝色为变化部分。

要点总结

  • 通过采用组合而非继承的手法,装饰器模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了使用继承带来的“灵活性差”和“多子类衍生”问题。
  • Decorator 装饰器类在接口上表现为 is-a Component 的继承关系,即Decorator装饰器类继承了Component 所具有的接口;但在实现上又表现为 has-a Component的组合关系,即Decorator装饰器类又使用了另外一个Component类。
  • 装饰器模式的目的并非解决“多子类衍生的多继承”问题,其应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。

来源:极客班——C++设计模式入门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86861.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86861.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86861.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea, CreateProcess error=206, 文件名或扩展名太长

idea, CreateProcess error206, 文件名或扩展名太长 解决 “CreateProcess error206, 文件名或扩展名太长” 错误 CreateProcess error206 是 Windows 系统特有的错误,表示命令行参数超出了 Windows 的 32767 字符限制。这个问题在 Java 开发中尤其常见&#xff0c…

一键高效率图片MD5修改工具PHP版

文章目录 图片MD5修改工具项目简介功能特点技术原理系统需求安装方法使用方法Web界面模式命令行模式文件结构常见问题注意事项开发者信息效果演示更多干货🎁1.如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “👍点赞” “✍️评论” “💙收藏” 一键三连哦!2.❤️…

跨主机用 Docker Compose 部署 PostgreSQL + PostGIS 主从

q下面是跨主机用 Docker Compose 部署 PostgreSQL PostGIS 主从复制的完整详细步骤(主库 从库),主从都用官方 PostGIS 镜像 postgis/postgis:15-3.3,并注意网络与持久化。复制即可。 🚩 跨主机 PostgreSQL PostGIS …

会议动态|千眼狼高速摄像机、DIC测量系统等科学仪器亮相第十五届全国爆炸力学学术会议

第十五届全国爆炸力学学术会议于6月28日在绍兴盛大召开,会议汇聚来自全国爆炸力学与冲击领域专家学者2000余人,聚焦“爆炸与冲击动力学工程应用”、“材料动态力学行为与损伤断裂“、“工程爆破与毁伤评估”、“含能材料与水中爆炸”、“结构动态响应与安…

vscode一个文件夹有残余的git仓库文件,已经失效了,怎样进行清空仓库残余文件并重新初始化git--ubuntu

vscode一个文件夹有残余的git仓库文件,已经失效了,怎样进行清空仓库残余文件并重新初始化git–ubuntu 首先要把工作区里重要的文件备份好,防止操作时数据丢失。删除.git文件夹 rm -rf .git初始化 (base) zd4090zd4090-System-Product-Name:…

6月30日作业

思维导图 一、读取文件&#xff0c;效果类似 cat 的功能 代码 #include <25041head.h>int main(int argc, const char *argv[]) {//打开文件printf("请输入你要读取的文件路径&#xff1a;");char str[128]"";scanf("%s",str);FILE *fpf…

ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法

我在Ubuntu 24.04.2 LTS下载源码安装Python 3.13.5时&#xff1a; #./configure --enable-loadable-sqlite-extensions --enable-optimizations #make 显示错误信息&#xff1a; Could not build the ssl module! Python requires a OpenSSL 1.1.1 or newer 查询我的openssl版…

Ai工具分享(2):Vscode+Cline无限免费的使用教程

大家好,我是程序员寒山。 今天给大家分享一个最新的免费使用的Ai插件Cline的方法,之前也给大家分享过一些免费的方案,但是这些都是随时在变化,之前推荐的很多都不能使用了。 Ai工具分享(2):Vscode+Cline无限免费的使用教 今天再给大家推荐一个,可以免费使用,且没有token…

Docker 目录迁移脚本【Windows Junction 类型链接】

Docker 目录迁移脚本完整教程&#xff1a;从诞生到自动化使用 一、脚本诞生背景与开发历程 1. 为什么需要迁移 Docker 目录&#xff1f; 系统盘空间压力&#xff1a;Docker 镜像和容器数据通常存储在C:\Users\用户名目录下&#xff0c;随着使用时间增长会占用大量系统盘空间…

spring-ai 工作流

目录 工作流概念工作流程图spring-boot 编码定义节点 (Node)定义节点图StateGraphcontroller测试浏览器测试用户输入 工作流概念 工作流是以相对固化的模式来人为地拆解任务&#xff0c;将一个大任务拆解为包含多个分支的固化流程。工作流的优势是确定性强&#xff0c;模型作为…

重头开始学ROS(6)---Eigen库安装与使用

Eigen库 矩阵运算是一种非常重要的运算方式&#xff0c;在Matlab中&#xff0c;矩阵运算可以轻松的实现&#xff0c;但在C这种偏底层的语言中&#xff0c;若不借助第三方库&#xff0c;矩阵运算需要我们进行较为复杂的代码设计。Eigen库是一个用于线性运算的C模板库&#xff0…

【STM32】外部中断

STM32 外部中断&#xff08;EXTI&#xff09;概述 这篇文章结合示例代码&#xff0c;系统性地讲述 STM32 外部中断&#xff08;EXTI&#xff09;实验的原理、以及配置流程。目的在于辅助读者掌握STM32F1 外部中断机制。 STM32F1xx官方资料&#xff1a;《STM32中文参考手册V10》…

LeetCode Hot100 算法题 (矩阵篇)

1、73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]// 将第一行…

Flutter基础(项目创建)

一、使用命令行创建项目 1. 确认 Flutter 环境正常 要保证 Flutter SDK 已经正确安装&#xff0c;并且环境变量配置无误。可以通过执行以下命令来验证&#xff1a; flutter doctor 要保证所有检查项都显示绿色对勾&#xff0c;要是有问题&#xff0c;可按照提示进行修复。 …

【Actix Web】Rust Web开发实战:Actix Web框架全面指南(2025企业级应用版)

​ 在2025年高并发、低延迟成为Web服务核心指标的背景下&#xff0c;​​Actix Web凭借异步Actor模型与零成本抽象​​&#xff0c;成为Rust生态中生产环境部署率最高的Web框架。本指南深入解析Actix Web 4.0核心技术&#xff0c;覆盖​​百万级并发架构设计​​、​​内存安全…

HTML之常用基础标签

HTML之常用基础标签 一、HTML文档基本结构标签1. <html>标签2. <head>标签3. <body>标签 二、文本相关基础标签1. 标题标签&#xff08;<h1> - <h6>&#xff09;2. 段落标签&#xff08;<p>&#xff09;3. 换行标签&#xff08;<br>…

外键列索引优化:加速JOIN查询的关键

在使用数据库时&#xff0c;特别是在执行涉及JOIN操作的查询时&#xff0c;优化外键列的索引是非常重要的。外键通常用于建立表之间的关联&#xff0c;而JOIN操作则是基于这些外键列来实现的。下面是一些关键步骤和技巧&#xff0c;可以帮助你优化外键列的索引&#xff0c;从而…

2025年 UI 自动化框架使用排行

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 </

【软考高项论文】论信息系统项目的整体管理

摘要 在信息系统项目的管理中&#xff0c;整体管理处于核心地位&#xff0c;对项目全局规划与协调起着关键作用&#xff0c;保障项目各阶段目标一致且高效执行。本文结合作者参与的 2024 年 6 月启动的信息系统项目&#xff0c;深入探讨项目整体管理的过程&#xff0c;着重阐述…

(4)Wireshark捕获设置

1.简介 WireShark的强大之处就在于不用你再做任何配置就可以抓取http或者https的包。主要是讲解和分享如何使用WireShark抓包。 2.运行Wireshark 安装好 Wireshark 以后&#xff0c;就可以运行它来捕获数据包了。方法如下&#xff1a; 1.在 Windows 的“开始”菜单中&#…