登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
每日签到
每天签到奖励2圆-6圆
发帖说明
VIP申请
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
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 }
复制代码
从上述实例中可以看出,各个装饰类只对装饰抽象类负责,职责单一。
各个装饰进行组合时,方便随意。新增装饰时,只需要新增一个继承自装饰抽象类的子类即可实现以原有装饰的随意组合使用。
四、总结:
想要扩展一个类的时候,传统的继承生成子类的形式,适用于扩展简单,并且不会多次扩展的情况下。
而如果一个类的扩展是周期性,多次扩展的或功能性比较相互独立的情况下,可以使用装饰器,可以有效的解决传统继承扩展子类膨胀的问题。
装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
装饰
模式
详解
相关帖子
mysql 主从架构详解
【软件测试】等待的艺术:详解显式等待与隐式等待,告别time.sleep!
多项式入门到进阶超详解
redis持久化详解
redis哨兵集群详解
KMP 模式串匹配算法讲解
详解智能体应用——网课生成Agent
设计模式之单例模式
Python 中多个装饰器执行顺序验证
JWT攻击详解与CTF实战
vip免费申请,1年只需15美金$
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
mysql 主从架构详解
0
1048
何书艺
2025-08-15
科技
【软件测试】等待的艺术:详解显式等待与隐式等待,告别time.sleep!
0
585
幌斛者
2025-08-21
安全
多项式入门到进阶超详解
0
556
马璞玉
2025-08-22
业界
redis持久化详解
0
389
石娅凉
2025-08-25
业界
redis哨兵集群详解
0
907
劳欣笑
2025-08-28
安全
KMP 模式串匹配算法讲解
0
316
赶塑坠
2025-09-02
安全
详解智能体应用——网课生成Agent
0
80
乱蚣
2025-09-03
安全
设计模式之单例模式
0
77
颖顿庐
2025-09-03
业界
Python 中多个装饰器执行顺序验证
0
268
接快背
2025-09-06
业界
JWT攻击详解与CTF实战
0
326
癖艺泣
2025-09-10
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
安全
签约作者
程序园优秀签约作者
发帖
蚣澡
2025-6-9 08:21:55
关注
0
粉丝关注
21
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9984
杭环
9988
凶契帽
9988
4
氛疵
9988
5
黎瑞芝
9988
6
猷咎
9986
7
里豳朝
9986
8
肿圬后
9986
9
蝓俟佐
9984
10
虽裘侪
9984
查看更多