当前位置:   article > 正文

C++ 结构型设计模式

C++ 结构型设计模式

C++ 设计模式自己理解整理笔记

结构型 - 适配器模式 

适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要作用是将一个类的接口转换成客户希望的另一个接口,
使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式主要有两种实现方式:类适配器模式和对象适配器模式。

类适配器

类适配器通过多重继承实现,这种方式利用了继承

优点
  1. 直接调用:由于适配器类继承了被适配类,所以可以直接调用被适配类的方法,性能可能会稍微好一些。
  2. 更简单:适配器和被适配类在同一个对象中,不需要间接调用。
缺点
  1. 多重继承的局限性:C++中的多重继承可能导致菱形继承问题,而且某些情况下可能会引入复杂性和维护难度。
  2. 不灵活:类适配器不能适配多个被适配类,适配器和被适配类的绑定在编译时确定,不如对象适配器灵活。
  1. #include <iostream>
  2. #include <string>
  3. // 目标接口
  4. class Target
  5. {
  6. public:
  7. virtual ~Target() = default;
  8. virtual void request() const = 0;
  9. };
  10. // 需要适配的类
  11. class Adaptee
  12. {
  13. public:
  14. void specificRequest() const
  15. {
  16. std::cout << "Adaptee: Specific request.\n";
  17. }
  18. };
  19. // 类适配器
  20. class Adapter : public Target, private Adaptee
  21. {
  22. public:
  23. void request() const override
  24. {
  25. specificRequest();
  26. }
  27. };
  28. int main()
  29. {
  30. target *target = new adapter();
  31. target->request();
  32. delete target;
  33. return 0;
  34. }

对象适配器

对象适配器通过在适配器类中包含一个指向被适配对象的指针来实现。这种方式利用了对象组合

优点
  1. 组合优于继承:对象适配器遵循了“组合优于继承”的设计原则。
  2. 灵活性:可以适配多个被适配类的对象,可以在运行时选择要适配的对象。
  3. 解耦:适配器和被适配对象之间的耦合度较低。
缺点
  1. 额外的间接层:因为需要通过指针间接调用被适配对象的方法,性能可能会略低于类适配器。
  1. #include <iostream>
  2. #include <string>
  3. // 目标接口
  4. class Target
  5. {
  6. public:
  7. virtual ~Target() = default;
  8. virtual void request() const = 0;
  9. };
  10. // 需要适配的类
  11. class Adaptee
  12. {
  13. public:
  14. void specificRequest() const
  15. {
  16. std::cout << "Adaptee: Specific request.\n";
  17. }
  18. };
  19. // 对象适配器
  20. class Adapter : public Target
  21. {
  22. private:
  23. Adaptee *adaptee;
  24. public:
  25. Adapter(Adaptee *a)
  26. : adaptee(a)
  27. {
  28. }
  29. void request() const override
  30. {
  31. adaptee->specificRequest();
  32. }
  33. };
  34. int main()
  35. {
  36. Adaptee *adptee = new Adaptee();
  37. Target *target = new Adapter(adptee);
  38. target->request();
  39. delete target;
  40. delete adptee;
  41. }

结构型 - 装饰器模式 

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许向一个现有对象添加新的功能,同时又不改变其结构。装饰器模式通过创建一个装饰类来包装原始类,可以在不改变原始类代码的情况下扩展其功能。以下是装饰器模式的主要优缺点:

优点

  1. 遵循开闭原则

    • 装饰器模式遵循开闭原则,即对扩展开放,对修改关闭。你可以通过添加新的装饰类来扩展对象的功能,而无需修改现有的代码。
  2. 灵活性

    • 可以在运行时动态地添加或撤销对象的功能。你可以根据需要随时组合不同的装饰器来改变对象的行为。
  3. 细粒度的功能扩展

    • 每个装饰器可以单独添加一个特定的功能,可以非常精细地控制对象的行为变化。
  4. 减少子类的数量

    • 通过使用装饰器模式,可以避免创建大量的子类来实现不同的功能组合,从而减少类的数量和复杂性。

缺点

  1. 增加复杂性

    • 装饰器模式会增加系统类的数量,并且由于使用了对象的递归组合,导致调试和排查问题时的复杂度增加。
  2. 创建大量的小对象

    • 每个功能的扩展都会创建一个新的装饰器对象,这可能导致系统中存在大量的小对象,从而增加内存开销。
  3. 依赖装饰器的顺序

    • 装饰器的功能可能依赖于其应用的顺序,不同的组合顺序可能导致不同的行为,这需要开发者非常小心地处理。
  4. 违背单一职责原则

    • 如果装饰器类的职责不明确,可能会导致单一职责原则被破坏。每个装饰器类应该只负责一个功能扩展,否则会增加类的复杂性和职责混乱。
      1. #include <iostream>
      2. #include <string>
      3. //动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更为灵活。
      4. //抽象类
      5. class Jbgz
      6. {
      7. public:
      8. virtual ~Jbgz() = default;
      9. virtual std::string GetName() = 0;
      10. virtual double GetMemary() = 0;
      11. };
      12. //实现类
      13. class SimpleJbgz : public Jbgz
      14. {
      15. public:
      16. virtual ~SimpleJbgz()
      17. {
      18. std::cout << "SimpleJbgz析构" << std::endl;
      19. }
      20. virtual std::string GetName() override
      21. {
      22. return "基本版 ";
      23. }
      24. virtual double GetMemary() override
      25. {
      26. return 5.5;
      27. }
      28. };
      29. class DecoratorJbgz : public Jbgz
      30. {
      31. public:
      32. ~DecoratorJbgz()
      33. {
      34. delete _jb;
      35. std::cout << "装饰类析构" << std::endl;
      36. }
      37. DecoratorJbgz(Jbgz *jb)
      38. : _jb(jb)
      39. {
      40. }
      41. protected:
      42. Jbgz *_jb = nullptr;
      43. };
      44. class EegJbgz : public DecoratorJbgz
      45. {
      46. public:
      47. ~EegJbgz()
      48. {
      49. std::cout << "Eeg析构" << std::endl;
      50. }
      51. EegJbgz(Jbgz *jb)
      52. : DecoratorJbgz(jb)
      53. {
      54. }
      55. std::string GetName() override
      56. {
      57. return _jb->GetName() + "Eeg ";
      58. }
      59. double GetMemary() override
      60. {
      61. return _jb->GetMemary() + 2.0;
      62. }
      63. };
      64. class LtJbgz : public DecoratorJbgz
      65. {
      66. public:
      67. ~LtJbgz()
      68. {
      69. std::cout << "LT析构" << std::endl;
      70. }
      71. LtJbgz(Jbgz *jb)
      72. : DecoratorJbgz(jb)
      73. {
      74. }
      75. std::string GetName() override
      76. {
      77. return _jb->GetName() + "Lt ";
      78. }
      79. double GetMemary() override
      80. {
      81. return _jb->GetMemary() + 1.0;
      82. }
      83. };
      84. int main()
      85. {
      86. Jbgz *simJb = new SimpleJbgz();
      87. std::cout << simJb->GetName() << std::endl;
      88. std::cout << simJb->GetMemary() << std::endl;
      89. simJb = new EegJbgz(simJb);
      90. std::cout << simJb->GetName() << std::endl;
      91. std::cout << simJb->GetMemary() << std::endl;
      92. simJb = new LtJbgz(simJb);
      93. std::cout << simJb->GetName() << std::endl;
      94. std::cout << simJb->GetMemary() << std::endl;
      95. delete simJb;
      96. return 0;
      97. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/823109
推荐阅读
相关标签
  

闽ICP备14008679号