使用场合
当需要给已经存在的一个类增加新的功能,同时又要保持接口不变,从目前的来看主要有以下方式:
1、通过继承,扩展原有类的功能,这是最简单的方式,但是如果又有新的功能加入,难道又要在此基
础上继承,显然这样会产生过多的继承关系
2、通过代理,如果使用代理模式也可以,代理模式中代理类与被代理类具有相同的接口,同时也可以在
代理类中扩充被代理类的功能,特别是使用动态代理效果更好,AOP就是使用动态代理来扩充被代理
类某些方面的功能,如日志功能,权限功能(如果希望了解动态代理,参见
原始类为被装饰对象,装饰器一方面要继承原始类,需要拥有和它一样的接口,同时又具有原始类的引
用,这样可以对任何继承自原始类的类型进行装饰,比如:原始类在经过装饰器A的装饰后,具有了装饰
器A所赋予的特殊功能,同时装饰器A又可以被装饰器B装饰,让原始类具有装饰器A、B的双重附加功能
以次类推,可以实现装饰器的自由组合。在WEB中的外观显示方面,使用不同的装饰器则可以定义不同
的外观。
同时根据面向对象中的职责单一的原则,我们可以定义出一系列职责单一的装饰器,增强系统灵活性。
使用案例:
下面我将通过一个简单的WinForm程序向大家展示装饰器模式所显示出来的魅力。
类图如下:
Machine将是需要被装饰的对象,AdvMachine是其继承的子类(本例中不打算实现它,只是为了图解直
观),MachineDecoraterBase是所有装饰器的基类,在它之下有三个面向不同方面的装饰器,分别是
LogDecorater(日志装饰器)、(NotifyDecorater)通知装饰器、(TransactionDecorater)事务装饰器。我将分别将
3个装饰器进行不同的组合,产生不同的装饰效果。
先来看看界面
通过一个按钮触发了Machine的Work方法,下面的复选框是表示如何对Machine进行装饰,选择的装饰器将应用于
machine上。下面的执行记录则显示是使用了装饰器后的效果。
Machine类的定义:
1
其中有一个简单的不能再简单的Work方法,返回一个字符串,这个方法将在后面被装饰。
MachineDecoraterBase类的定义:
1
该类一方面实现了被装饰对象的接口,一方面可以通过容纳一个也同样实现了被修饰对象的接口的对象,该对象将在装饰器中被装饰。
接下来是LogDecorater:
1
该类进行了日志装饰。NotifyDecorater装饰类:
1
TransactionDecorater装饰类:
1
我们在客户端对以上类进行调用:
1
}
可见,客户的调用接口是没有变的(还是使用Machine),但是显示内容却改变了,如下图几个不同的装饰组合
(不好意思,写到这里才发现界面上我把事务写成事物了,我也懒的再截图,将就凑合吧)
学过AOP的人看了可能会有似曾相识的感觉,的确这个例子使用动态代理来实现也能达到同样的效
果,动态代理可以通过拦截方法调用来为一个对象织入某个方面的额外的功能。可见动态代理能实现的
某些功能,使用装饰器也能实现。
本示例完整的程序代码可以到https://files.cnblogs.com/mixiaobo/DecoratePatternDemo.rar下载