意图/目的/定义(intent)

(简短的描述该模式的作用。)
装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

动机(motivation)

(动机给出来问题以及如何解决这个问题的具体场景。)
星巴兹咖啡的订单实现。

适用性(applicability)

(适用性描述模式可以被应用在什么场合。)

结构(structure)

(结构提供了图示,显示出参与此模式的类之间的关系。)
image.png

参与者(participants)

(参与者描述在此设计中所涉及到的类和对象在模式中的责任和角色。)

协作(collaborations)

(协作告诉我们参与者如何在此模式中合作。)

实现/范例代码(implementation/sample code)

(实现提供了你在实现该模式时需要使用的技巧,以及你应该小心面对的问题。)
(范例代码提供代码的片段,可能对你的实现有多帮助。)

  1. /// 饮料抽象类
  2. abstract class Beverage {
  3. String description = "Unknown Beverage";
  4. String getDescription() {
  5. return description;
  6. }
  7. double cost();
  8. }
  9. /// 调料抽象类,继承饮料类
  10. abstract class CondimentDecorator extends Beverage {
  11. // 调料类装饰者重新实现getDescription()方法
  12. String getDescription();
  13. }
  14. /// --------------- 饮料代码
  15. // 浓缩咖啡是一种饮料,继承Beverage类
  16. class Espresso extends Beverage {
  17. Espresso() {
  18. description = 'Espresso';
  19. }
  20. @override
  21. double cost() {
  22. return 1.99;
  23. }
  24. }
  25. /// 综合咖啡,继承自Beverage类
  26. class HouseBlend extends Beverage {
  27. HouseBlend() {
  28. description = 'House Blend Coffee';
  29. }
  30. @override
  31. double cost() {
  32. return 0.89;
  33. }
  34. }
  35. // 深培咖啡
  36. class DarkRoast extends Beverage {
  37. DarkRoast() {
  38. description = 'Dark Roast Coffee';
  39. }
  40. @override
  41. double cost() {
  42. return 0.99;
  43. }
  44. }
  45. /// ------------------ 调料代码
  46. // 摩卡是一个装饰者调料,所以它扩展自CondimentDecorator。
  47. class Mocha extends CondimentDecorator {
  48. // 用一个实例变量记录饮料,也就是被装饰者。
  49. // 想办法让被装饰着被记录到实例变量中。
  50. // 这里的做法是:把饮料当做构造器函数的参数,有构造函数将饮料记录在实例变量中。
  51. Beverage _beverage;
  52. Mocha(Beverage beverage) {
  53. this._beverage = beverage;
  54. }
  55. // 我们希望叙述不只是描述饮料,而是完整的连调料都描述出来。
  56. // 首先利用委托的做法,得到一个叙述,然后在其后加上附加的叙述。
  57. @override
  58. String getDescription() {
  59. return '${_beverage.getDescription()}, Mocha';
  60. }
  61. @override
  62. double cost() {
  63. // 要计算mocha饮料的价钱。
  64. // 首先把调用委托给被装饰者对象,以计算价钱,然后再加上mocha的价钱,得到最后结果
  65. return 0.20 + _beverage.cost();
  66. }
  67. }
  68. // 豆浆
  69. class Soy extends CondimentDecorator {
  70. Beverage _beverage;
  71. Soy(Beverage beverage) {
  72. _beverage = beverage;
  73. }
  74. @override
  75. String getDescription() {
  76. return '${_beverage.getDescription()}, Soy';
  77. }
  78. @override
  79. double cost() {
  80. return 0.15 + _beverage.cost();
  81. }
  82. }
  83. // 奶泡
  84. class Whip extends CondimentDecorator {
  85. Beverage _beverage;
  86. Whip(Beverage beverage) {
  87. _beverage = beverage;
  88. }
  89. @override
  90. String getDescription() {
  91. return '${_beverage.getDescription()}, Whip';
  92. }
  93. @override
  94. double cost() {
  95. return 0.10 + _beverage.cost();
  96. }
  97. }
  98. // 牛奶
  99. class Milk extends CondimentDecorator {
  100. Beverage _beverage;
  101. Milk(Beverage beverage) {
  102. _beverage = beverage;
  103. }
  104. @override
  105. String getDescription() {
  106. return '${_beverage.getDescription()}, Milk';
  107. }
  108. @override
  109. double cost() {
  110. return 0.10 + _beverage.cost();
  111. }
  112. }
  113. /// 测试函数
  114. main(List<String> args) {
  115. Beverage beverage = new Espresso();
  116. print('${beverage.getDescription()} \$ ${beverage.cost()}');
  117. Beverage beverage2 = new DarkRoast();
  118. beverage2 = new Mocha(beverage2);
  119. beverage2 = new Milk(beverage2);
  120. beverage2 = new Whip(beverage2);
  121. print('${beverage2.getDescription()} \$ ${beverage2.cost()}');
  122. Beverage beverage3 = new HouseBlend();
  123. beverage3 = new Mocha(beverage3);
  124. beverage3 = new Mocha(beverage3);
  125. beverage3 = new Soy(beverage3);
  126. print('${beverage3.getDescription()} \$ ${beverage3.cost()}');
  127. }

已知应用(known uses)

(已知应用用来描述已经在真实系统中发现的模式例子。)

相关模式(related patterns)

(相关模式描述了此模式和其他模式之间的关系。)

OO知识

OO基础

  1. 抽象
  2. 封装
  3. 多态
  4. 继承

OO原则

  1. 封装变化
  2. 多用组合少用继承
  3. 针对接口编程,不针对实现编程
  4. 为交互对象之间的松耦合设计而努力
  5. 对扩展开放,对修改关闭

    要点

  6. 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。

  7. 在我们的设计中,应该允许行为可以被扩展,而无需修改现有的代码。
  8. 组合和委托可用于在运行时动态的加上新的行为。
  9. 除了继承,装饰者模式也可以让我们扩展行为。
  10. 装饰者模式意味着一群装饰者类,这些类用来包装具体组件。
  11. 装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)。
  12. 装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
  13. 你可以用无数个装饰者包装一个组件。
  14. 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。
  15. 装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂。