• 设计模式8、装饰者模式 Decorator


    解释说明:动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案
    抽象构件(Component):定义一个抽象接口以规范准备收附加责任的对象
    具体构件(ConcreteComponent):实现抽象构件,通过装饰角色为其添加一些职责
    抽象装饰类(Decorator):继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
    具体装饰类(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任
    优点:
        Decorator 模式与继承关系的目的都是要扩展对象的功能,但是 Decorator 可以提供比继承更多的灵活性。
        通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
    缺点:
        这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
        装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
        装饰模式是针对抽象构建(Component)类型编程。但是,如果要针对具体构件(ConcreteComponent)编程,应该重新思考应用架构,以及装饰者是否合适。当然也可改变 Component 接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
    适用场景
        需要扩展一个类的功能,或给一个类添加附加职责。
        需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
        需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
        当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类
    1. #pragma once
    2. #include
    3. using namespace std;
    4. // 所有饮料的基类
    5. class IBeverage
    6. {
    7. public:
    8. virtual string Name() = 0; // 名称
    9. virtual double Cost() = 0; // 价钱
    10. };
    11. /********** 具体的饮料(咖啡)**********/
    12. // 黑咖啡,属于混合咖啡
    13. class HouseBlend : public IBeverage
    14. {
    15. public:
    16. string Name() {
    17. return "HouseBlend";
    18. }
    19. double Cost() {
    20. return 30.0;
    21. }
    22. };
    23. // 深度烘培咖啡豆
    24. class DarkRoast : public IBeverage
    25. {
    26. public:
    27. string Name() {
    28. return "DarkRoast";
    29. }
    30. double Cost() {
    31. return 28.5;
    32. }
    33. };
    34. #pragma once
    35. #include "component.h"
    36. // 调味品
    37. class CondimentDecorator : public IBeverage
    38. {
    39. public:
    40. CondimentDecorator(IBeverage* beverage) : m_pBeverage(beverage) {}
    41. string Name() {
    42. return m_pBeverage->Name();
    43. }
    44. double Cost() {
    45. return m_pBeverage->Cost();
    46. }
    47. protected:
    48. IBeverage* m_pBeverage;
    49. };
    50. /********** 具体的饮料(调味品)**********/
    51. // 奶油
    52. class Cream : public CondimentDecorator
    53. {
    54. public:
    55. Cream(IBeverage* beverage) : CondimentDecorator(beverage) {}
    56. string Name() {
    57. return m_pBeverage->Name() + " Cream";
    58. }
    59. double Cost() {
    60. return m_pBeverage->Cost() + 3.5;
    61. }
    62. };
    63. // 摩卡
    64. class Mocha : public CondimentDecorator
    65. {
    66. public:
    67. Mocha(IBeverage* beverage) : CondimentDecorator(beverage) {}
    68. string Name() {
    69. return m_pBeverage->Name() + " Mocha";
    70. }
    71. double Cost() {
    72. return m_pBeverage->Cost() + 2.0;
    73. }
    74. };
    75. // 糖浆
    76. class Syrup : public CondimentDecorator
    77. {
    78. public:
    79. Syrup(IBeverage* beverage) : CondimentDecorator(beverage) {}
    80. string Name() {
    81. return m_pBeverage->Name() + " Syrup";
    82. }
    83. double Cost() {
    84. return m_pBeverage->Cost() + 3.0;
    85. }
    86. };
    87. #include "component.h"
    88. #include "decorator.h"
    89. #include
    90. #ifndef SAFE_DELETE
    91. #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
    92. #endif
    93. int main()
    94. {
    95. /********** 黑咖啡 **********/
    96. IBeverage* pHouseBlend = new HouseBlend();
    97. cout << pHouseBlend->Name() << " : " << pHouseBlend->Cost() << endl;
    98. // 黑咖啡 + 奶牛
    99. CondimentDecorator* pCream = new Cream(pHouseBlend);
    100. cout << pCream->Name() << " : " << pCream->Cost() << endl;
    101. // 黑咖啡 + 摩卡
    102. CondimentDecorator* pMocha = new Mocha(pHouseBlend);
    103. cout << pMocha->Name() << " : " << pMocha->Cost() << endl;
    104. // 黑咖啡 + 糖浆
    105. CondimentDecorator* pSyrup = new Syrup(pHouseBlend);
    106. cout << pSyrup->Name() << " : " << pSyrup->Cost() << endl;
    107. /********** 深度烘培咖啡豆 **********/
    108. IBeverage* pDarkRoast = new DarkRoast();
    109. cout << pDarkRoast->Name() << " : " << pDarkRoast->Cost() << endl;
    110. // 深度烘培咖啡豆 + 奶油
    111. CondimentDecorator* pCreamDR = new Cream(pDarkRoast);
    112. cout << pCreamDR->Name() << " : " << pCreamDR->Cost() << endl;
    113. // 深度烘培咖啡豆 + 奶油 + 摩卡
    114. CondimentDecorator* pCreamMocha = new Mocha(pCreamDR);
    115. cout << pCreamMocha->Name() << " : " << pCreamMocha->Cost() << endl;
    116. // 深度烘培咖啡豆 + 奶油 + 摩卡 + 糖浆
    117. CondimentDecorator* pCreamMochaSyrup = new Syrup(pCreamMocha);
    118. cout << pCreamMochaSyrup->Name() << " : " << pCreamMochaSyrup->Cost() << endl;
    119. SAFE_DELETE(pSyrup);
    120. SAFE_DELETE(pMocha);
    121. SAFE_DELETE(pCream);
    122. SAFE_DELETE(pHouseBlend);
    123. SAFE_DELETE(pCreamMochaSyrup);
    124. SAFE_DELETE(pCreamMocha);
    125. SAFE_DELETE(pCreamDR);
    126. SAFE_DELETE(pDarkRoast);
    127. getchar();
    128. return 0;
    129. }

     

  • 相关阅读:
    C++11多线程
    【题库】咸鱼之王答题挑战题库大全
    Ubuntu22.04.4 - vim - 笔记
    Go Web——Gin使用中间件
    SSM运动器材共享平台毕业设计源码201816
    2020年下半年~2022下半年下午题易错总结
    IDEA 高效插件工具
    电子画册如何制作,教你几分钟简单上手制作?
    ASEMI肖特基二极管MBR40200PT参数和作用详解
    postgresql14-表的管理(四)
  • 原文地址:https://blog.csdn.net/u013480226/article/details/133440327