当前位置:   article > 正文

C++设计模式——Bridge桥接模式

C++设计模式——Bridge桥接模式

一,桥接模式简介

桥接模式是一种结构型设计模式,用于将抽象与实现分离,这里的"抽象"和"实现"都有可能是接口函数或者类。

桥接模式让抽象与实现之间解耦合,使得开发者可以更关注于实现部分,调用者(Client)可以更关注于抽象部分。

桥接模式可以将一个复杂的类进行拆分为好几个类,开发者可以修改其中任意一个类的实现,而不影响其他类的正常运行,该模式可以降低代码的维护工作量,降低代码风险。

桥接模式的核心就是:抽象化(Abstraction)与实现化(Implementation)

抽象化:忽略一些细节,将具有共同特征的不同实体抽象为同一个对象。

实现化:为抽象化提供具体的逻辑和代码实现。

举个例子:

假设有一堆几何体,这些几何体有形状、颜色等特征,形状有:矩形、圆形,颜色有:红色、蓝色。

为了使用类来描述这些几何体,我们可以将他们抽象为四个子类:红色矩形,蓝色矩形,红色圆形,蓝色圆形。

按照以上方式,如果几何体还包含更多种类的形状和颜色,例如椭圆、绿色,那么这些特征通过排列组合产生的子类将会呈指数级增长。如果此时使用桥接模式,将会大大降低类与类之间的耦合,减少了开发期间的代码量。

对应UML类图:

桥接模式将继承关系改为组合关系,对于以上几何体的描述,我们使用一个类来描述几何体的矩形、圆形等形状,我们使用另一个类来描述几何体的红色、蓝色等颜色,最后将这两个类的实例进行组合。当需要改变类的颜色或形状的实现时,无需修改整个类的实现,只需要修改颜色或形状的实现即可。

对应UML类图:

二,桥接模式的结构

桥接模式主要涉及的类:
1. 抽象角色类:是一个类,定义了统一的对外接口,并定义了接口的组成结构,但是不包含接口对应的具体实现。
2. 具体实现类:是一个或多个类,该类包含了对抽象角色类的接口的具体代码实现。这些类可以根据需求变化而独立变化,且不会影响到其他类的功能。具体实现类与抽象角色类之间的关联方式采用的是组合而非继承。
3. 桥接类:充当了抽象角色类和具体实现类之间的桥梁,负责维护抽象角色类和具体实现类之间的关系,它允许客户端在运行时选择使用哪个具体实现类。
桥接模式的主要组件:
1.Abstraction:抽象类,提供统一的抽象接口。内部包含对Implementor类对象的引用。
2.RefinedAbstraction:扩充抽象类,有的教程里面称为"ExtendedAbstraction",Abstraction的子类,扩充Abstraction的抽象接口。
3.Implementor:实现类,提供了实现类的接口,这个接口的功能和以上的抽象接口不同。
4.ConcreteImplementor:提供了实现类的接口对应的代码逻辑。
桥接模式UML类图:

代码实现: 

  1. #include <iostream>
  2. class Implementation {
  3. public:
  4. virtual ~Implementation() {}
  5. virtual std::string newOperation() const = 0;
  6. };
  7. class ConcreteImplementationA : public Implementation {
  8. public:
  9. std::string newOperation() const override {
  10. return "ConcreteImplementationA: Here's the result on the platform A.\n";
  11. }
  12. };
  13. class ConcreteImplementationB : public Implementation {
  14. public:
  15. std::string newOperation() const override {
  16. return "ConcreteImplementationB: Here's the result on the platform B.\n";
  17. }
  18. };
  19. class Abstraction {
  20. protected:
  21. Implementation* implementation_;
  22. public:
  23. Abstraction(Implementation* implementation) : implementation_(implementation) {
  24. }
  25. virtual ~Abstraction() {
  26. }
  27. virtual std::string doOperation() const {
  28. return "Abstraction: Base operation with:\n" +
  29. this->implementation_->newOperation();
  30. }
  31. };
  32. class RefinedAbstraction : public Abstraction {
  33. public:
  34. RefinedAbstraction(Implementation* implementation) : Abstraction(implementation) {
  35. }
  36. std::string doOperation() const override {
  37. return "RefinedAbstraction: Extended operation with:\n" +
  38. this->implementation_->newOperation();
  39. }
  40. };
  41. void ClientCode(const Abstraction& abstraction) {
  42. std::cout << abstraction.doOperation();
  43. }
  44. int main() {
  45. Implementation* implementation_1 = new ConcreteImplementationA;
  46. Abstraction* abstraction_1 = new Abstraction(implementation_1);
  47. ClientCode(*abstraction_1);
  48. std::cout << std::endl;
  49. delete implementation_1;
  50. delete abstraction_1;
  51. Implementation* implementation_2 = new ConcreteImplementationB;
  52. Abstraction* abstraction_2 = new RefinedAbstraction(implementation_2);
  53. ClientCode(*abstraction_2);
  54. delete implementation_2;
  55. delete abstraction_2;
  56. return 0;
  57. }

运行结果: 

  1. Abstraction: Base operation with:
  2. ConcreteImplementationA: Here's the result on the platform A.
  3. RefinedAbstraction: Extended operation with:
  4. ConcreteImplementationB: Here's the result on the platform B.

三,桥接模式的应用场景

系统组件升级:当需要为现有系统增加新功能或替换已有功能,但又不希望改变原有接口时。

跨平台应用开发:使用桥接模式来处理不同操作系统或硬件平台的差异,例如在移动端APP应用中,UI组件同时兼容ios和Android平台。

第三方插件开发:使用桥接模式开发出可支持多种第三方服务的组件,例如移动支付api。

API扩展:当API的功能需要被扩展,又希望保持原有API的稳定时,使用桥接模式可以隐藏实现细节。

四,桥接模式的优缺点

桥接模式的优点:

分离接口的抽象与实现部分。

替代了继承的实现方式,代码的可复用性更强。

桥接模式可以修改任意一个模块的功能实现而不影响整个系统。

可以向用户隐藏实现细节。

降低了类之间的依赖性。

代码的可维护性很强,可以根据需求灵活地更换实现模块。

桥接模式的缺点:

引入了额外的抽象层,使系统变得更复杂。

会额外增加系统的理解与设计难度。

接口调用增多,带来额外的性能开销。

五,代码实战

代码实战: 

生产不同颜色和不同车型的汽车

  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. class IColor
  5. {
  6. public:
  7. virtual string Color() = 0;
  8. };
  9. class RedColor : public IColor
  10. {
  11. public:
  12. string Color()
  13. {
  14. return "of Red Color";
  15. }
  16. };
  17. class BlueColor : public IColor
  18. {
  19. public:
  20. string Color()
  21. {
  22. return "of Blue Color";
  23. }
  24. };
  25. class ICarModel
  26. {
  27. public:
  28. virtual string WhatIsMyType() = 0;
  29. };
  30. class Model_A : public ICarModel
  31. {
  32. IColor* _myColor;
  33. public:
  34. Model_A(IColor *obj) :_myColor(obj){}
  35. string WhatIsMyType()
  36. {
  37. return "I am a Model_A " + _myColor->Color();
  38. }
  39. };
  40. class Model_B : public ICarModel
  41. {
  42. IColor* _myColor;
  43. public:
  44. Model_B(IColor *obj) :_myColor(obj){}
  45. string WhatIsMyType()
  46. {
  47. return "I am a Model_B " + _myColor->Color();;
  48. }
  49. };
  50. int main()
  51. {
  52. IColor* red = new RedColor();
  53. IColor* blue = new BlueColor();
  54. ICarModel* modelA = new Model_B(red);
  55. ICarModel* modelB = new Model_A(blue);
  56. cout << "\n" << modelA->WhatIsMyType();
  57. cout << "\n" << modelB->WhatIsMyType() << "\n\n";
  58. delete red;
  59. delete blue;
  60. return 0;
  61. }

运行结果:

  1. I am a Model_B of Red Color
  2. I am a Model_A of Blue Color

六,参考阅读

https://refactoring.guru/design-patterns/bridge

https://design-patterns.readthedocs.io/zh-cn/latest/structural_patterns/bridge.html

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

闽ICP备14008679号