登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
签到
每天签到奖励2-10圆
导读
排行榜
TG频道
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
VIP申请
VIP网盘
网盘
联系我们
发帖说明
每日签到
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
c#装饰器模式详解
c#装饰器模式详解
[ 复制链接 ]
蚣澡
2025-6-9 08:21:55
一、基础介绍:
动态地给一个对象添加一些额外的职责。适用于需要扩展一个类的功能,或给一个类添加多个变化的情况。
装饰器,顾名思义就是在原有基础上添加一些功能。
大家都只知道如果想单纯的给原有类增加一些功能,可以直接继续该类生成一个子类就可以。
举个例子,如果现在有个手机类,想给手机贴膜,传统的做法就是新建一个手机类的子类(手机贴膜子类),继承自手机类。
使用这个子类就可以完成对手机的贴膜操作。
那如果又想给手机按保护壳的话,传统做法有两种,可以继续新建一个手机类的子类(手机保护壳子类),继承自手机类。
使用这个子类可以给手机按保护壳,但也就失去了给手机贴膜的功能。另一种做法,新建一个手机贴膜类的子类(手机贴膜+保护壳),也就是手机类的子子类。
这样即可以贴膜也可以按手机壳。
大家思考一个问题,如果有很多个装饰并且想随意组合的话,那就有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 }
复制代码
从上述实例中可以看出,各个装饰类只对装饰抽象类负责,职责单一。
各个装饰进行组合时,方便随意。新增装饰时,只需要新增一个继承自装饰抽象类的子类即可实现以原有装饰的随意组合使用。
四、总结:
想要扩展一个类的时候,传统的继承生成子类的形式,适用于扩展简单,并且不会多次扩展的情况下。
而如果一个类的扩展是周期性,多次扩展的或功能性比较相互独立的情况下,可以使用装饰器,可以有效的解决传统继承扩展子类膨胀的问题。
装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
装饰
模式
详解
相关帖子
Kubernetes Service详解:实现服务发现与负载均衡
C# 弃元模式:从语法糖到性能利器的深度解析
PWA(渐进式网页应用)详解和应用场景(AI)
嵌入式固件升级框架详解与实战经验
三类代码协同模式,你要如何选?
最小二乘问题详解5:非线性最小二乘求解实例
Stimulsoft 报表脚本执行模式风险与防护建议
CRC32的直接和反转模式
freeswitch的proxy_media模式下video流的问题与修正
VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
vip免费申请,1年只需15美金$
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
Kubernetes Service详解:实现服务发现与负载均衡
1
733
骆贵
2025-10-09
业界
C# 弃元模式:从语法糖到性能利器的深度解析
1
53
南宫玉英
2025-10-10
业界
PWA(渐进式网页应用)详解和应用场景(AI)
0
279
醋辛
2025-10-10
业界
嵌入式固件升级框架详解与实战经验
0
215
尝琨
2025-10-10
安全
三类代码协同模式,你要如何选?
0
334
跟尴
2025-10-10
业界
最小二乘问题详解5:非线性最小二乘求解实例
0
680
赵淳美
2025-10-16
业界
Stimulsoft 报表脚本执行模式风险与防护建议
0
123
讣丢
2025-10-17
安全
CRC32的直接和反转模式
0
525
蒲善思
2025-10-17
业界
freeswitch的proxy_media模式下video流的问题与修正
0
934
唐茗
2025-10-17
业界
VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
0
3
顶豌
2025-10-20
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
蚣澡
2025-6-9 08:21:55
关注
0
粉丝关注
26
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
anyue1937
9994893
dage888
999994
3934307807
992122
4
富账慕
9977
5
邹语彤
9979
6
二艰糖
9997
7
刎唇
9993
8
匝抽
9986
9
聚怪闩
9960
10
孙淼淼
9977
查看更多