• 设计模式7、桥接模式 Bridge


    解释说明:将抽象部分与它的实现部分解耦,使得两者都能够独立变化
    桥接模式将两个独立变化的维度设计成两个独立的继承等级结构(而不会将两者耦合在一起形成多层继承结构),在抽象层将二者建立起一个抽象关联,该关联关系类似一座桥,将两个独立的等级结构连接起来,故曰“桥接模式”
    抽象类(Abstraction):定义抽象类,并包含一个对实现化对象的引用
    扩充抽象类(RefinedAbstraction):是抽象化类的子类,实现父类那个中的业务方法,并通过组合关系调用实现化角色中的业务方法
    实现类(Implementor):定义实现化角色的接口,供扩展抽象化角色调用
    具体实现(ConcreteImplementor):给出实现化角色接口的具体实现
    优点:
        分离抽象和实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。
    在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
        桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。
    缺点:
        桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
    桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。
    适用场景
        如果一个系统需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。
        “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
    一个系统存在多个(≥ 2)独立变化的维度,且这多个维度都需要独立进行扩展。
    对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
    1. #pragma once
    2. #include
    3. // 电器
    4. class IElectricalEquipment
    5. {
    6. public:
    7. virtual ~IElectricalEquipment() {}
    8. // 打开
    9. virtual void PowerOn() = 0;
    10. // 关闭
    11. virtual void PowerOff() = 0;
    12. };
    13. // 电灯
    14. class Light : public IElectricalEquipment
    15. {
    16. public:
    17. // 开灯
    18. virtual void PowerOn() override {
    19. std::cout << "Light is on." << std::endl;
    20. }
    21. // 关灯
    22. virtual void PowerOff() override {
    23. std::cout << "Light is off." << std::endl;
    24. }
    25. };
    26. // 风扇
    27. class Fan : public IElectricalEquipment
    28. {
    29. public:
    30. // 打开风扇
    31. virtual void PowerOn() override {
    32. std::cout << "Fan is on." << std::endl;
    33. }
    34. // 关闭风扇
    35. virtual void PowerOff() override {
    36. std::cout << "Fan is off." << std::endl;
    37. }
    38. };
    39. #pragma once
    40. #include "implementor.h"
    41. // 开关
    42. class ISwitch
    43. {
    44. public:
    45. ISwitch(IElectricalEquipment* ee) { m_pEe = ee; }
    46. virtual ~ISwitch() {}
    47. // 打开电器
    48. virtual void On() = 0;
    49. // 关闭电器
    50. virtual void Off() = 0;
    51. protected:
    52. IElectricalEquipment* m_pEe;
    53. };
    54. // 拉链式开关
    55. class PullChainSwitch : public ISwitch
    56. {
    57. public:
    58. PullChainSwitch(IElectricalEquipment* ee) : ISwitch(ee) {}
    59. // 用拉链式开关打开电器
    60. virtual void On() override {
    61. std::cout << "Switch on the equipment with a pull chain switch." << std::endl;
    62. m_pEe->PowerOn();
    63. }
    64. // 用拉链式开关关闭电器
    65. virtual void Off() override {
    66. std::cout << "Switch off the equipment with a pull chain switch." << std::endl;
    67. m_pEe->PowerOff();
    68. }
    69. };
    70. // 两位开关
    71. class TwoPositionSwitch : public ISwitch
    72. {
    73. public:
    74. TwoPositionSwitch(IElectricalEquipment* ee) : ISwitch(ee) {}
    75. // 用两位开关打开电器
    76. virtual void On() override {
    77. std::cout << "Switch on the equipment with a two-position switch." << std::endl;
    78. m_pEe->PowerOn();
    79. }
    80. // 用两位开关关闭电器
    81. virtual void Off() override {
    82. std::cout << "Switch off the equipment with a two-position switch." << std::endl;
    83. m_pEe->PowerOff();
    84. }
    85. };
    86. #include "abstraction.h"
    87. #include "implementor.h"
    88. #ifndef SAFE_DELETE
    89. #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
    90. #endif
    91. int main()
    92. {
    93. // 创建电器 - 电灯、风扇
    94. IElectricalEquipment* light = new Light();
    95. IElectricalEquipment* fan = new Fan();
    96. /**
    97. * 创建开关 - 拉链式开关、两位开关
    98. * 将拉链式开关和电灯关联起来,将两位开关和风扇关联起来
    99. **/
    100. ISwitch* pullChain = new PullChainSwitch(light);
    101. ISwitch* twoPosition = new TwoPositionSwitch(fan);
    102. // 开灯、关灯
    103. pullChain->On();
    104. pullChain->Off();
    105. // 打开风扇、关闭风扇
    106. twoPosition->On();
    107. twoPosition->Off();
    108. SAFE_DELETE(twoPosition);
    109. SAFE_DELETE(pullChain);
    110. SAFE_DELETE(fan);
    111. SAFE_DELETE(light);
    112. getchar();
    113. return 0;
    114. }

  • 相关阅读:
    将CSV、Excel、XML文件转换为MySQL数据库
    神经网络和深度学习-均方误差Mean Square Error
    UDP多播
    基于华为云云耀云服务器L实例开展性能评测|MySQL性能测评
    活性基团功能化PEG纳米金包Fe3O4磁纳米颗粒
    TP-link TL-R473G配置pppoe账号分配网络上网
    Pytorch优化器全总结(二)Adadelta、RMSprop、Adam、Adamax、AdamW、NAdam、SparseAdam
    NISP中渗透测试需要记录的专业术语
    【Java数据结构】详解Stack与Queue(四)
    Revit翻模教程:怎么在体量内绘制圆锥?
  • 原文地址:https://blog.csdn.net/u013480226/article/details/133440304