登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
1
2
/ 2 页
下一页
返回列表
首页
›
业界区
›
业界
›
c#装饰器模式详解
c#装饰器模式详解
[ 复制链接 ]
蚣澡
2025-6-9 08:21:55
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
一、基础介绍:
动态地给一个对象添加一些额外的职责。适用于需要扩展一个类的功能,或给一个类添加多个变化的情况。
装饰器,顾名思义就是在原有基础上添加一些功能。
大家都只知道如果想单纯的给原有类增加一些功能,可以直接继续该类生成一个子类就可以。
举个例子,如果现在有个手机类,想给手机贴膜,传统的做法就是新建一个手机类的子类(手机贴膜子类),继承自手机类。
使用这个子类就可以完成对手机的贴膜操作。
那如果又想给手机按保护壳的话,传统做法有两种,可以继续新建一个手机类的子类(手机保护壳子类),继承自手机类。
使用这个子类可以给手机按保护壳,但也就失去了给手机贴膜的功能。另一种做法,新建一个手机贴膜类的子类(手机贴膜+保护壳),也就是手机类的子子类。
这样即可以贴膜也可以按手机壳。
大家思考一个问题,如果有很多个装饰并且想随意组合的话,那就有N个子类并且存在很深的继承链路。
想要解决这个问题,就可以用到装饰器了。
比如贴膜装饰、保护壳装饰、贴纸装饰等等,它们都是独立存在的,只继承自装饰器类。
什么意思呢?就是说给手机贴膜的时候它并不会给手机按保护壳的功能,职责单一,贴膜装饰器只负责给手机贴膜。
这样做有什么好处呢?好处就是这些装饰可以随意组合,比如即想贴膜又想按保护壳,就可以将贴膜装饰+保护壳装饰进组组合。
在装饰器模式中各个角色有:
抽象构件(Component)角色
:规范手机的构成
具体构件(ConcreteComponent)角色
:继承自抽象构件,具体实现手机。(大多情况下,可以省略抽象构件,抽象装饰类可以直接继承)
抽象装饰类(Decorator)角色
:创建一个构件(Component)对象的实例,可以使用这个实例调用原构件的功能,并规范装饰类。
具体装饰类(ConcreteDecorator)角色
:继承自抽象装饰类,具体实现该装饰功能。
二、应用场景:
原有类无法修改或者修改困难的情况下,对类进行多次扩展或功能性比较相互独立,有效防止多次扩展的情况下子类的膨胀。
注:如果类的扩展比较简单,并且不会多次进行扩展的情况下直接使用类的继承生成子类的方式更为方便快捷。
三、创建方式:
为了方便说明,以下实例就不创建抽象构件了。
首先先看下不使用装饰器进行类的扩展
1 /// <summary>
2 /// 手机类
3 /// </summary>
4 public class Phone
5 {
6 public void Print()
7 {
8 Console.WriteLine("手机");
9 }
10 }
11
12 /// <summary>
13 /// 手机贴膜
14 /// </summary>
15 public class Sticker : Phone
16 {
17 public Sticker()
18 {
19 base.Print();
20 }
21
22 /// <summary>
23 /// 进行贴膜
24 /// </summary>
25 public void AddSticker()
26 {
27 Console.WriteLine("给手机贴膜");
28 }
29 }
30
31 /// <summary>
32 /// 手机保护壳
33 /// </summary>
34 public class ProtectiveCase : Phone
35 {
36 public ProtectiveCase()
37 {
38 base.Print();
39 }
40
41 /// <summary>
42 /// 按保护壳
43 /// </summary>
44 public void AddProtectiveCase()
45 {
46 Console.WriteLine("给手机按保护壳");
47 }
48 }
49
50 /// <summary>
51 /// 即贴膜又按保护壳
52 /// </summary>
53 public class ProtectiveCaseAndSticker : Sticker
54 {
55 public ProtectiveCaseAndSticker()
56 {
57 }
58
59 /// <summary>
60 /// 按保护壳
61 /// </summary>
62 public void AddProtectiveCase()
63 {
64 Console.WriteLine("给手机按保护壳");
65 }
66 }
67
68 /// <summary>
69 /// 客户端
70 /// </summary>
71 class Client
72 {
73 static void Main(string[] args)
74 {
75 //创建一个手机
76 Phone phone = new Phone();
77 phone.Print();
78 Console.WriteLine("\r\n");
79
80 //给手机贴膜
81 Sticker sticker = new Sticker();
82 sticker.AddSticker();
83 Console.WriteLine("\r\n");
84
85 //给手机按保护壳
86 ProtectiveCase protectiveCase = new ProtectiveCase();
87 protectiveCase.AddProtectiveCase();
88 Console.WriteLine("\r\n");
89
90 //即贴膜又按保护壳
91 ProtectiveCaseAndSticker protectiveCaseAndSticker = new ProtectiveCaseAndSticker();
92 protectiveCaseAndSticker.AddSticker();
93 protectiveCaseAndSticker.AddProtectiveCase();
94 Console.ReadKey();
95 }
96 }
复制代码
通过上述实例可以看出,如果各个扩展功能比较独立的话可以直接进行继承扩展。
如果各个功能直接有交集的情况下,会造成很深的继承关系。
比如上述实例中,如果单独贴膜或者单独安装保护壳则直接继承手机类即可。
但如果想要即贴膜又要安装保护壳,各自继承手机类的方式就行不通了,只能在贴膜类或者保护壳类的基础上进行扩展。
如果还有添加手机挂饰,那就还需要再一层继承关系。
要解决这个问题就用到了装饰器,下面看看使用装饰器是怎么给手机添加新功能的。
使用装饰器模式对类进行扩展
1 /// <summary>
2 /// 手机类
3 /// </summary>
4 public class Phone
5 {
6 public void Print()
7 {
8 Console.WriteLine("手机");
9 }
10 }
11
12 /// <summary>
13 /// 装饰抽象类
14 /// </summary>
15 public abstract class Decorator : Phone
16 {
17 private Phone phone;
18
19 public Decorator(Phone p)
20 {
21 this.phone = p;
22 }
23
24 public abstract void AddDecorator();
25 }
26
27 /// <summary>
28 /// 贴膜装饰
29 /// </summary>
30 public class Sticker : Decorator
31 {
32 public Sticker(Phone p)
33 : base(p)
34 {
35 }
36
37 public override void AddDecorator()
38 {
39 Console.WriteLine("给手机贴膜");
40 }
41 }
42
43 /// <summary>
44 /// 保护壳装饰
45 /// </summary>
46 public class ProtectiveCase : Decorator
47 {
48 public ProtectiveCase(Phone p)
49 : base(p)
50 {
51 }
52
53 /// <summary>
54 /// 按保护壳
55 /// </summary>
56 public override void AddDecorator()
57 {
58 Console.WriteLine("给手机按保护壳");
59 }
60 }
61
62 /// <summary>
63 /// 客户端
64 /// </summary>
65 class Client
66 {
67 static void Main(string[] args)
68 {
69 //单独给手机贴膜
70 Phone phone = new Phone();
71 phone.Print();
72 Decorator sticker = new Sticker(phone);
73 sticker.AddDecorator();
74
75 //单独给手机按保护壳
76 phone = new Phone();
77 phone.Print();
78 Decorator protectiveCase = new ProtectiveCase(phone);
79 protectiveCase.AddDecorator();
80 Console.WriteLine("\r\n");
81
82 //即贴膜又按保护壳
83 phone = new Phone();
84 phone.Print();
85 //首先创建贴膜装饰实例,将手机对象传入
86 Decorator decorator = new Sticker(phone);
87 //进行贴膜操作
88 decorator.AddDecorator();
89 //创建保护壳装饰实例,将贴膜后的手机对象传入
90 decorator = new ProtectiveCase(decorator);
91 //进行按保护壳操作
92 decorator.AddDecorator();
93 Console.ReadKey();
94 }
95 }
复制代码
从上述实例中可以看出,各个装饰类只对装饰抽象类负责,职责单一。
各个装饰进行组合时,方便随意。新增装饰时,只需要新增一个继承自装饰抽象类的子类即可实现以原有装饰的随意组合使用。
四、总结:
想要扩展一个类的时候,传统的继承生成子类的形式,适用于扩展简单,并且不会多次扩展的情况下。
而如果一个类的扩展是周期性,多次扩展的或功能性比较相互独立的情况下,可以使用装饰器,可以有效的解决传统继承扩展子类膨胀的问题。
装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
装饰
模式
详解
相关帖子
__block 变量内存布局详解
TCP/IP协议详解:高性能服务器开发的底层基石
Block Copy 的内存布局详解
ACIS SAT 文件格式详解及其解析
ACIS SAT 文件格式详解及其解析
Android R8适配全流程详解
1、SEATA分布式事务——XA模式
笔记:WPF MVVM 模式下通过消息机制获取自定义对话框数据
2、SEATA分布式事务——AT模式
torch.nn神经网络详解
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
__block 变量内存布局详解
0
708
裴涛
2026-03-20
业界
TCP/IP协议详解:高性能服务器开发的底层基石
0
698
汲佩杉
2026-03-20
业界
Block Copy 的内存布局详解
0
17
郁兰娜
2026-03-22
安全
ACIS SAT 文件格式详解及其解析
0
213
韶又彤
2026-03-23
安全
ACIS SAT 文件格式详解及其解析
0
898
碛物
2026-03-23
安全
Android R8适配全流程详解
0
811
羽桑
2026-03-27
业界
1、SEATA分布式事务——XA模式
0
963
能杜孱
2026-03-28
安全
笔记:WPF MVVM 模式下通过消息机制获取自定义对话框数据
0
438
锑砖
2026-03-28
安全
2、SEATA分布式事务——AT模式
0
10
申倩语
2026-03-30
业界
torch.nn神经网络详解
0
4
雌鲳签
2026-03-31
回复
(35)
仲秀娟
2025-12-9 15:55:57
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
yyds。多谢分享
吟氅
2025-12-10 11:53:48
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
前排留名,哈哈哈
箝德孜
2026-1-4 12:43:34
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
用心讨论,共获提升!
溥价
2026-1-8 21:01:58
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢,下载保存了
袁勤
2026-1-15 04:02:05
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
懂技术并乐意极积无私分享的人越来越少。珍惜
圉棺
2026-1-15 19:04:17
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
新版吗?好像是停更了吧。
懵诬哇
2026-1-18 02:11:16
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
感谢分享,学习下。
焦和玉
2026-1-18 09:23:56
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
用心讨论,共获提升!
存叭
2026-1-21 12:16:37
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
前排留名,哈哈哈
姜删懔
2026-1-21 15:48:22
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
热心回复!
钦娅芬
2026-1-21 17:13:32
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
很好很强大 我过来先占个楼 待编辑
孜尊
2026-1-23 13:59:50
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢发布原创作品,程序园因你更精彩
颛孙中
2026-1-26 02:46:22
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
东西不错很实用谢谢分享
丘奕奕
2026-1-28 05:09:18
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
东西不错很实用谢谢分享
谷江雪
2026-1-28 09:41:14
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
前排留名,哈哈哈
丘娅楠
2026-2-4 07:38:05
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
收藏一下 不知道什么时候能用到
宗和玉
2026-2-6 09:09:05
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢发布原创作品,程序园因你更精彩
济曝喊
2026-2-6 12:39:53
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
谢谢分享,试用一下
宁觅波
2026-2-9 04:36:50
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
感谢分享,学习下。
下一页 »
1
2
/ 2 页
下一页
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
蚣澡
2026-2-9 04:36:50
关注
0
粉丝关注
33
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991125
anyue1937
9994892
kk14977
6845359
4
xiangqian
638210
5
神泱
9537
6
宋子
9883
7
韶又彤
9911
8
诀锺
9036
9
荪俗
9020
10
蓬森莉
9871
查看更多
今日好文热榜
6
host怎么设置,host设置教程
245
2026国内图床深度选型指南:从需求到实测,
874
Claude Code源码泄露:8大隐藏功能曝光
674
没有技术要求,只需5步就能完成数据分析和
388
完整项目实战
764
Python 数据类型:数字、字符串与容器
823
从“救火”到“预判”:AIOps 如何用 AI 重
598
Redis 单线程真的是单线程吗?源码角度全面
426
突发!Claude Code 51万行源码全网裸奔:一
495
使用 OpenSpec + 提示词工程 + Harness 思
528
.NET 进阶之路:异步、并发与内存管理的系
497
Java 中的 实现、泛型
977
Go + Vue 接入行为验证码完整指南
624
Python 面向对象编程:从入门到实践
766
Python 面向对象编程:从入门到实践
540
Mem0:给 AI Agent 装上「长期记忆」
757
Mem0:给 AI Agent 装上「长期记忆」
632
我用 Codex 和 Gemini,做了一个本地桌面版
428
Go + Vue 接入行为验证码完整指南
510
Mem0:给 AI Agent 装上「长期记忆」