单从名字上来看, 装饰器模式就是对被装饰对象的一种修饰,放到程序当中来说就是对对象的功能进行额外的扩展。装饰器模式的定义也是这样描述的:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
UML图可以表示如下:
1、场景描述
现在大多数人都喜欢养上一只宠物狗,喜欢给他穿点衣服啥的,这种外表大打扮也就是一种装饰, 下面通过代码的方式,来实现给小狗穿衣服、鞋子的功能。
2、实现
/// <summary>/// 狗的接口/// </summary>public interface IDog{/// <summary>/// 展示/// </summary>void Display();}/// <summary>/// 具体实现/// </summary>public class Dog : IDog{public void Display(){Console.WriteLine("一只小狗");}}/// <summary>/// 装饰器/// </summary>public abstract class Decorator : IDog{private IDog _dog;public Decorator(IDog dog){_dog = dog;}public virtual void Display(){_dog.Display();}}/// <summary>/// 衣服装饰/// </summary>public class ClothesDecorator : Decorator{public ClothesDecorator(IDog dog) : base(dog){}public override void Display(){base.Display();Console.WriteLine("为小狗穿上衣服"); ;}}/// <summary>/// 鞋子装饰/// </summary>public class ShoesDecorator : Decorator{public ShoesDecorator(IDog dog) : base(dog){}public override void Display(){base.Display();Console.WriteLine("为小狗穿上鞋子");}}// 客户端调用Console.WriteLine("***************原来的小狗****************");IDog dog = new Dog();dog.Display();Console.WriteLine("***************穿上衣服的小狗****************");IDog clothesDog = new ClothesDecorator(dog);clothesDog.Display();Console.WriteLine("***************穿上鞋子的小狗****************");IDog shoesDog = new ShoesDecorator(dog);shoesDog.Display();Console.WriteLine("***************穿上衣服、鞋子的小狗****************");IDog allDog = new ShoesDecorator(clothesDog);allDog.Display();
3、优缺点
从上面的代码我们可以看出, 我们通过对构造函数传入不同IDog对象,达到不同的目的。这一点充分的提现了装饰器设计模式的灵活性。不仅可以选择装饰的对象,而且还可以决定装饰的顺序。
所以,大概来说,装饰器设计模式有如下优点:
- 灵活,可以动态的扩展功能。
- 通过不同的排列组合,可以实现不同的效果
- 遵守开闭原则
当然,装饰器模式实现了如上的灵活扩展性,那我们也可以注意到:
- 装饰器模式增加了许多子类,在一定程度上会增加代码的复杂性、降低可维护性。
4、应用场景
上面的例子可以看出来, 使用装饰器模式只是对对象的一种装饰。 既然是装饰, 那么不管怎么装饰那原对象本身还是它自己。 就像上面例子中描述的小狗一样, 不管给它穿上衣服还是鞋子,或者还有别的装饰。 但始终它都一只小狗。
所以对于装饰器模式来说, 它注重的是功能的扩展、加强,装饰以后还是对象本身。 对于外界如何调用,并不是装饰器模式关心的事情。但是同时需要兼顾对象的其它功能,因为再怎么装饰,本质也是对象本身,要担负起对象应有的职责。。就像上面的例子中那样:我提供了衣服和鞋子的装饰器, 但是对于具体装饰哪一项,或者具体的装饰顺序这就是由客户端自己来决定了。
