news 2026/8/8 0:28:00

设计模式[9]——装饰器模式一分钟彻底说清楚

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式[9]——装饰器模式一分钟彻底说清楚

设计模式[9]——装饰器模式一分钟彻底说透

一句话定义

在不修改原有对象的前提下,运行时动态、透明地给对象层层添加额外行为,保持接口不变。

软件领域真实例子:网络数据流处理(超级常见!)

场景:你有一个基本的网络 Socket 发送数据,但实际项目中经常需要层层叠加功能

  • 先加密(Encryption)
  • 再压缩(Compression)
  • 再加日志记录(Logging)
  • 最后才真正发送

客户端代码只关心stream->write(data),完全不知道中间加了多少层处理!

不用装饰器会怎样?继承爆炸:

classEncryptedSocket:publicSocket{...}classEncryptedCompressedSocket:publicEncryptedSocket{...}classEncryptedCompressedLoggedSocket:publicEncryptedCompressedSocket{...}// 3种功能 → 8种子类!明天加“校验和”功能?直接崩溃。
很多人困惑:这不就是普通的继承多态吗?

错得离谱!下面这张表10秒彻底撕开:

项目普通继承多态(你觉得像的)装饰器模式(真相)
添加行为时机静态:编译时固定在子类里动态:运行时随意叠加、顺序随意、数量随意
类数量功能组合爆炸(2^n 个子类)只有 n + 1 个类(基础 + n种装饰)
灵活性想临时加/减一层功能?不可能运行时随意包装:想加双重加密?包两层就行
关系本质is-a(EncryptedSocket “是一种” Socket)has-a(装饰器“持有”一个被装饰的对象)
软件真实场景固定类型:TcpSocket、UdpSocket临时增强:加密流、压缩流、日志流、缓冲流
口号“焊死在子类里”“运行时层层叠加,想加就加,想拆就拆”

狠话:继承是生孩子——生完就定型;装饰器是穿外套——想穿几件、哪件先穿都行,还能脱!

真实软件代码(现代 C++20,网络流处理)
#include<iostream>#include<memory>#include<string>#include<vector>usingnamespacestd;// 1. 统一数据流接口classDataStream{public:virtual~DataStream()=default;virtualvoidwrite(constvector<uint8_t>&data)=0;virtualstringname()const=0;// 用于调试描述};// 2. 基础流(真正干活的核心)classTcpSocketStream:publicDataStream{public:voidwrite(constvector<uint8_t>&data)override{cout<<"[TcpSocket] 真正发送数据,长度: "<<data.size()<<" 字节"<<endl;}stringname()constoverride{return"TCP Socket";}};// 3. 装饰器基类(关键:持有一个流指针)classStreamDecorator:publicDataStream{protected:unique_ptr<DataStream>stream;// ← 包装链的核心public:explicitStreamDecorator(unique_ptr<DataStream>s):stream(move(s)){}stringname()constoverride{returnstream->name();// 默认转发,子类可追加}};// 4. 具体装饰器(真实功能)classLoggingDecorator:publicStreamDecorator{public:explicitLoggingDecorator(unique_ptr<DataStream>s):StreamDecorator(move(s)){}voidwrite(constvector<uint8_t>&data)override{cout<<"[Logging] 记录写操作,数据大小: "<<data.size()<<endl;stream->write(data);// 转发给下一层}stringname()constoverride{returnstream->name()+" + Logging";}};classCompressionDecorator:publicStreamDecorator{public:explicitCompressionDecorator(unique_ptr<DataStream>s):StreamDecorator(move(s)){}voidwrite(constvector<uint8_t>&data)override{cout<<"[Compression] 正在压缩数据... (原大小 "<<data.size()<<" -> 压缩后 "<<data.size()/2<<")"<<endl;autocompressed=compress(data);// 模拟压缩stream->write(compressed);}stringname()constoverride{returnstream->name()+" + Compression";}private:vector<uint8_t>compress(constvector<uint8_t>&d){return{1,2,3};}// 简化};classEncryptionDecorator:publicStreamDecorator{public:explicitEncryptionDecorator(unique_ptr<DataStream>s):StreamDecorator(move(s)){}voidwrite(constvector<uint8_t>&data)override{cout<<"[Encryption] 正在AES加密数据..."<<endl;autoencrypted=encrypt(data);// 模拟加密stream->write(encrypted);}stringname()constoverride{returnstream->name()+" + Encryption";}private:vector<uint8_t>encrypt(constvector<uint8_t>&d){return{9,9,9};}// 简化};
客户端:运行时随意组装流
intmain(){vector<uint8_t>payload={1,2,3,4,5,6,7,8,9,0};// 场景1:生产环境 - 全功能autostream=make_unique<TcpSocketStream>();stream=make_unique<LoggingDecorator>(move(stream));stream=make_unique<CompressionDecorator>(move(stream));stream=make_unique<EncryptionDecorator>(move(stream));cout<<"当前流: "<<stream->name()<<endl;// TCP Socket + Logging + Compression + Encryptionstream->write(payload);// 场景2:调试环境 - 只加日志,不加密不压缩autodebugStream=make_unique<TcpSocketStream>();debugStream=make_unique<LoggingDecorator>(move(debugStream));debugStream->write(payload);// 场景3:想双重加密?轻松!autosecureStream=make_unique<TcpSocketStream>();secureStream=make_unique<EncryptionDecorator>(move(secureStream));secureStream=make_unique<EncryptionDecorator>(move(secureStream));// 双重加密!secureStream->write(payload);}
C++ 真实项目里到处都是装饰器
  • 标准库std::ostreamstd::ofstreamstd::stringstream(层层包装)
  • Boost.Asio:socket → ssl::stream → buffered_stream
  • Qt:QWidget → QScrollArea(滚动条装饰) → CustomBorderDecorator
  • 游戏网络:Packet → CRCDecorator → EncryptDecorator → CompressDecorator → Send
  • 日志库:Logger → FileWriter → AsyncDecorator → RotateDecorator
终极口诀(软件人专属)

“功能运行时叠,层层包装不继承;
接口不变真优雅,加密压缩随便配!”

刻在DNA里的一句话

当你在软件中需要“运行时给一个流/对象临时叠加多个处理行为”(日志、加密、压缩、缓冲等),且组合方式多变时,
别用继承爆炸,用装饰器——层层包装,接口统一,灵活到极致!

现在,装饰器模式在纯软件场景下彻底说透了吧?
这才是程序员每天都在用的真实模式!

下一期要外观模式(Facade),它专门治“子系统太复杂”的病!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 15:29:30

设计模式[10]——外观模式一分钟彻底说清楚

设计模式[10]——外观模式&#xff08;Facade&#xff09;一分钟彻底说透&#xff08;C版软件领域真实例子&#xff09; 一句话定义 为一个复杂子系统提供一个简洁、高层接口&#xff0c;隐藏内部的复杂性&#xff0c;让客户端“一键启动”或“一键操作”整个系统。 最狠的比喻…

作者头像 李华
网站建设 2026/8/7 23:42:18

Temu 分销重塑跨境生态:轻资产时代的新增长法则

库存与资金的沉重枷锁&#xff0c;以及全球履约的复杂迷宫&#xff0c;始终是跨境卖家增长道路上的主要障碍&#xff0c;在此背景下&#xff0c;Temu全球分销平台的推出&#xff0c;标志着一场“轻资产”运营革命的兴起&#xff0c;它并非简单的选品工具&#xff0c;而是一套系…

作者头像 李华
网站建设 2026/8/7 23:00:38

Hello World的深度演进:一个Ascend C标量算子的性能剖析之旅

目录 摘要 1. 引言&#xff1a;为什么从"最简单"的算子开始&#xff1f; 2. 技术原理&#xff1a;达芬奇架构下的标量计算本质 2.1 &#x1f3d7;️ 架构设计理念&#xff1a;计算-内存-通信三位一体 2.2 ⚙️ 核心算法实现&#xff1a;从朴素到极致 2.2.1 版本…

作者头像 李华
网站建设 2026/8/6 23:38:21

[Python桌面开发] 本地多服务启动神器:Python + Tkinter 构建“进程批量启动与监控工具”(跨平台 GUI + 源码开放)

在日常本地开发或运维环境中,我们常常面临这样的困扰: 本地有多个服务/脚本/微服务需要频繁启动调试? Windows/Linux 切换时手动运行脚本繁琐且易出错? systemctl 命令记不住?cmd 命令太多维护难? 本文带你实战构建一个用 Python + Tkinter 实现的图形化服务启动与监控工…

作者头像 李华
网站建设 2026/8/7 23:45:21

量子算法的实现路径解析(工业级应用稀缺技术曝光)

第一章&#xff1a;量子算法的实现量子计算利用叠加态和纠缠等量子力学特性&#xff0c;为解决某些经典计算机难以处理的问题提供了全新路径。实现量子算法需要结合量子编程框架、量子门操作以及对量子比特状态的精确控制。目前主流的量子开发工具如Qiskit、Cirq和Quil使得开发…

作者头像 李华
网站建设 2026/8/6 23:59:57

揭秘Python最被低估的8个标准库,第6个能省下你一半代码量

第一章&#xff1a;揭开Python最被低估标准库的神秘面纱在Python庞大的标准库生态中&#xff0c;许多开发者往往聚焦于如requests、numpy或flask等热门第三方库&#xff0c;却忽视了那些内置于语言核心、功能强大却鲜为人知的标准模块。其中&#xff0c;pathlib便是最具代表性的…

作者头像 李华