单从名字上来看, 装饰器模式就是对被装饰对象的一种修饰,放到程序当中来说就是对对象的功能进行额外的扩展。装饰器模式的定义也是这样描述的:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
UML图可以表示如下:
image.png

1、场景描述

现在大多数人都喜欢养上一只宠物狗,喜欢给他穿点衣服啥的,这种外表大打扮也就是一种装饰, 下面通过代码的方式,来实现给小狗穿衣服、鞋子的功能。

2、实现

  1. /// <summary>
  2. /// 狗的接口
  3. /// </summary>
  4. public interface IDog
  5. {
  6. /// <summary>
  7. /// 展示
  8. /// </summary>
  9. void Display();
  10. }
  11. /// <summary>
  12. /// 具体实现
  13. /// </summary>
  14. public class Dog : IDog
  15. {
  16. public void Display()
  17. {
  18. Console.WriteLine("一只小狗");
  19. }
  20. }
  21. /// <summary>
  22. /// 装饰器
  23. /// </summary>
  24. public abstract class Decorator : IDog
  25. {
  26. private IDog _dog;
  27. public Decorator(IDog dog)
  28. {
  29. _dog = dog;
  30. }
  31. public virtual void Display()
  32. {
  33. _dog.Display();
  34. }
  35. }
  36. /// <summary>
  37. /// 衣服装饰
  38. /// </summary>
  39. public class ClothesDecorator : Decorator
  40. {
  41. public ClothesDecorator(IDog dog) : base(dog)
  42. {
  43. }
  44. public override void Display()
  45. {
  46. base.Display();
  47. Console.WriteLine("为小狗穿上衣服"); ;
  48. }
  49. }
  50. /// <summary>
  51. /// 鞋子装饰
  52. /// </summary>
  53. public class ShoesDecorator : Decorator
  54. {
  55. public ShoesDecorator(IDog dog) : base(dog)
  56. {
  57. }
  58. public override void Display()
  59. {
  60. base.Display();
  61. Console.WriteLine("为小狗穿上鞋子");
  62. }
  63. }
  64. // 客户端调用
  65. Console.WriteLine("***************原来的小狗****************");
  66. IDog dog = new Dog();
  67. dog.Display();
  68. Console.WriteLine("***************穿上衣服的小狗****************");
  69. IDog clothesDog = new ClothesDecorator(dog);
  70. clothesDog.Display();
  71. Console.WriteLine("***************穿上鞋子的小狗****************");
  72. IDog shoesDog = new ShoesDecorator(dog);
  73. shoesDog.Display();
  74. Console.WriteLine("***************穿上衣服、鞋子的小狗****************");
  75. IDog allDog = new ShoesDecorator(clothesDog);
  76. allDog.Display();

上面的代码用UML可以表示如下:
image.png

3、优缺点

从上面的代码我们可以看出, 我们通过对构造函数传入不同IDog对象,达到不同的目的。这一点充分的提现了装饰器设计模式的灵活性。不仅可以选择装饰的对象,而且还可以决定装饰的顺序。
所以,大概来说,装饰器设计模式有如下优点:

  • 灵活,可以动态的扩展功能。
  • 通过不同的排列组合,可以实现不同的效果
  • 遵守开闭原则

当然,装饰器模式实现了如上的灵活扩展性,那我们也可以注意到:

  • 装饰器模式增加了许多子类,在一定程度上会增加代码的复杂性、降低可维护性。

    4、应用场景

    上面的例子可以看出来, 使用装饰器模式只是对对象的一种装饰。 既然是装饰, 那么不管怎么装饰那原对象本身还是它自己。 就像上面例子中描述的小狗一样, 不管给它穿上衣服还是鞋子,或者还有别的装饰。 但始终它都一只小狗。
    所以对于装饰器模式来说, 它注重的是功能的扩展、加强,装饰以后还是对象本身。 对于外界如何调用,并不是装饰器模式关心的事情。但是同时需要兼顾对象的其它功能,因为再怎么装饰,本质也是对象本身,要担负起对象应有的职责。。就像上面的例子中那样:我提供了衣服和鞋子的装饰器, 但是对于具体装饰哪一项,或者具体的装饰顺序这就是由客户端自己来决定了。