装饰模式
4.1、装饰模式的特点
装饰模式:装饰模式主要是解决了,我们以动态的,透明的形式为某个类型添加一个新的职责,客户程序可以不知道我们具体添加的功能职责,而客户程序只是根据对象提供的方法进行调用即可。而具体职责操作留给装饰对象去完成。
我们这里给出装饰模式的经典模式的类图:
我们这里对这个经典结构进行稍微的说明:我们这里结合我们上面的播放器来说
1、对于Compnent,我们定义一个IPlayer这样的接口,我们接口中定义方法,Play()方法。
2、然后我们把要装饰这个播放器的装饰类型进行抽象,抽象出接口IDecorator接口。这个即可继承自IPlayer接口。
3、接着,我们定义一个简单的播放器对象,实现这个IPlayer接口。
4、我们实现播放音乐和视频文件的装饰类型的实现。
5、我们将简单的播放器对象,通过装饰对象进行装饰,为这个简单播放器套上一层一层的外壳,使其具有播放音乐和视频的功能。
4.2、装饰模式的使用场景
1、当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。
2、适应于某个对象的职责经常发生变化或者经常需要动态的增加职责,避免因为这种为了适应这样的变化,而增加继承子类扩展的方式,因为这种方式为 造成,子类膨胀的速度过快,难以控制。
五、装饰模式的经典实现
经过上面的简单描述,我想大家很想知道装饰模式的经典实现方案吧!我们来结合播放器的实例来分析实现,下面给出核心代码:
///<summary>/// 播放器的普通实现类 ///</summary>publicclass Player : IPlayer { #region IPlayer 成员
publicvoid Play() { thrownew NotImplementedException(); }
#endregion }
// <summary> // 装饰器接口 // </summary>publicinterface IDecorator : IPlayer
///<summary>/// 装饰器的抽象基类 ///</summary>publicabstractclass DecoratorBase : IDecorator { protected IPlayer play =null; public DecoratorBase(IPlayer player) { this.play = player; }
#region IPlayer 成员
publicabstractvoid Play();
#endregion }
///<summary>/// 音乐播放器装饰器 ///</summary>publicclass MusicDecorator : DecoratorBase { public MusicDecorator(IPlayer play) : base(play) { } publicoverridevoid Play() { thrownew NotImplementedException(); } }
///<summary>/// 视频播放器装饰类 ///</summary>publicclass VedioDecorator : DecoratorBase { public VedioDecorator(IPlayer play) : base(play) { } publicoverridevoid Play() { thrownew NotImplementedException(); } }
具体的测试调用代码如下:
经过了2次的装饰后,该播放器对象,可以播放任何格式的文件。通过上面的过程,我们发现了我们在使用装饰模式的时候,有如下几点我们需要把我好:
1、我们在开发的过程中,如果需要为某个类型添加多个职责的时候,我们需要多个装饰实现类,这样类太多的时候,我们需要将这个对象装饰多次。
2、我们对我们的装饰过的对象,如何指定的撤销某个装饰过程的状态呢?类似我们使用某些应用程序中的undo操作。
3、对于动态装饰的对象,我们debug的时候,我们很难跟踪和调试。
六、装饰模式的其他方案
一、通过配置文件来完成装饰操作
具体的操作过程如下:配置文件中配置对象要完成的装饰步骤,通过公共的配置读取类,通过字典缓存装饰的步骤,然后传入普通的对象,返回装饰后的对象。
我们这里给出配置文件的格式:
我们来看具体的装饰器步骤构造器代码:
foreach (IDecorator item in list) { play = (T)Activator.CreateInstance(item.GetType(), play); }
return play; } }
二、通过特性+反射的形式来组织装饰的过程 这里就不给出具体的实现代码了,下篇或者后续给出分析几类基于特性+标记的实现方案。大伙也可以提出其他的不同实现思路。
七、装饰模式使用总结
通过上面的讲述,我们知道装饰模式,特别适合对某个类型的对象,动态的增加新的职责,应用程序就像使用原来的对象一样使用对象新增的装饰后的功能,装饰模式就好像是穿了一层层的外壳,这样的方式避免了通过继承来为类型添加新的职责的形式可取,通过继承的方式容易造成子类的膨胀,但是当装饰类太多的时候,也是个难以维护的问题,至少是在装饰对象的时候,我们可能需要多步操作来完成对象的装饰,这时候我们可以同上面提出的改进的方案,来完成自动配置装饰模式,记录操作模式的状态,可以进行有效的回滚操作,以完成撤销操作