[设计模式] 设计模式课程(六)-- 桥接模式

概述

  • 属于“单一职责”模式(子类膨胀,需要划清职责)
  • 属于结构型模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而在开发时分别使用
  • 动机:某些类型固有的实现逻辑,使得它们有多个变化的维度
  • 如何应对多维度变化,如何利用面向对象技术来使得类型可以轻松沿着多个方向变化,而不引入额外的复杂度?
  • 将不同变化方向的函数(平台实现(Login / SendMessage)/业务抽象(PlaySound() / DrawShape()))放在两个类中
  • 将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化
  • 使用了对象间的组合关系解耦了抽象和现实间固有的绑定关系,使得抽象和实现可以沿着各自的维度变化
  • Bridge类似于多继承,但多继承往往违背单一职责原则(一个类只有一个变化原因),复用性差
  • 将实际程序分为抽象部分(用户界面[GUI])和实现部分(底层操作系统代码[API]),GUI调用API对用户的操作做出响应
  • 可以在两个独立方向对应用进行扩展,如开发多个GUI(面向普通用户和管理员),支持多个不同的API(面向Windows,Linux,MacOS)
  • 客户端代码将实现对象传递给抽象部分的构造函数,此后只需与抽象部分打交互,而无需操作实现对象

  

示例1

  • bridge1.cpp:1+n+m*n
  • bridge2.cpp:1+n+m
  • imp->OperationImp(); 相当于 MessagerImp* messagerImp;
  • Implementor 相当于 MessagerImp
  • ConcreteImplementor A 相当于 PCMessagerImp
  • RefinedAbstraction 相当于 MessagerLite, MessagerPerfect

bridge1.cpp

  1 class Messager{
  2 public:
  3     virtual void Login(string username, string password)=0;
  4     virtual void SendMessage(string message)=0;
  5     virtual void SendPicture(Image image)=0;
  6 
  7     virtual void PlaySound()=0;
  8     virtual void DrawShape()=0;
  9     virtual void WriteText()=0;
 10     virtual void Connect()=0;
 11     
 12     virtual ~Messager(){}
 13 };
 14 
 15 //平台实现
 16 
 17 class PCMessagerBase : public Messager{
 18 public:
 19     
 20     virtual void PlaySound(){
 21         //**********
 22     }
 23     virtual void DrawShape(){
 24         //**********
 25     }
 26     virtual void WriteText(){
 27         //**********
 28     }
 29     virtual void Connect(){
 30         //**********
 31     }
 32 };
 33 
 34 class MobileMessagerBase : public Messager{
 35 public:
 36     
 37     virtual void PlaySound(){
 38         //==========
 39     }
 40     virtual void DrawShape(){
 41         //==========
 42     }
 43     virtual void WriteText(){
 44         //==========
 45     }
 46     virtual void Connect(){
 47         //==========
 48     }
 49 };
 50 
 51 //业务抽象
 52 
 53 class PCMessagerLite : public PCMessagerBase {
 54 public:
 55     
 56     virtual void Login(string username, string password){
 57         
 58         PCMessagerBase::Connect();
 59         //........
 60     }
 61     virtual void SendMessage(string message){
 62         
 63         PCMessagerBase::WriteText();
 64         //........
 65     }
 66     virtual void SendPicture(Image image){
 67         
 68         PCMessagerBase::DrawShape();
 69         //........
 70     }
 71 };
 72 
 73 class PCMessagerPerfect : public PCMessagerBase {
 74 public:
 75     
 76     virtual void Login(string username, string password){
 77         
 78         PCMessagerBase::PlaySound();
 79         //********
 80         PCMessagerBase::Connect();
 81         //........
 82     }
 83     virtual void SendMessage(string message){
 84         
 85         PCMessagerBase::PlaySound();
 86         //********
 87         PCMessagerBase::WriteText();
 88         //........
 89     }
 90     virtual void SendPicture(Image image){
 91         
 92         PCMessagerBase::PlaySound();
 93         //********
 94         PCMessagerBase::DrawShape();
 95         //........
 96     }
 97 };
 98 
 99 class MobileMessagerLite : public MobileMessagerBase {
100 public:
101     
102     virtual void Login(string username, string password){
103         
104         MobileMessagerBase::Connect();
105         //........
106     }
107     virtual void SendMessage(string message){
108         
109         MobileMessagerBase::WriteText();
110         //........
111     }
112     virtual void SendPicture(Image image){
113         
114         MobileMessagerBase::DrawShape();
115         //........
116     }
117 };
118 
119 class MobileMessagerPerfect : public MobileMessagerBase {
120 public:
121     
122     virtual void Login(string username, string password){
123         
124         MobileMessagerBase::PlaySound();
125         //********
126         MobileMessagerBase::Connect();
127         //........
128     }
129     virtual void SendMessage(string message){
130         
131         MobileMessagerBase::PlaySound();
132         //********
133         MobileMessagerBase::WriteText();
134         //........
135     }
136     virtual void SendPicture(Image image){
137         
138         MobileMessagerBase::PlaySound();
139         //********
140         MobileMessagerBase::DrawShape();
141         //........
142     }
143 };
144 
145 void Process(){
146         //编译时装配
147         Messager *m =
148             new MobileMessagerPerfect();
149 }
View Code

bridge2.cpp

  1 class Messager{
  2 protected:
  3      MessagerImp* messagerImp;//...
  4 public:
  5     virtual void Login(string username, string password)=0;
  6     virtual void SendMessage(string message)=0;
  7     virtual void SendPicture(Image image)=0;
  8     
  9     virtual ~Messager(){}
 10 };
 11 
 12 class MessagerImp{
 13 public:
 14     virtual void PlaySound()=0;
 15     virtual void DrawShape()=0;
 16     virtual void WriteText()=0;
 17     virtual void Connect()=0;
 18     
 19     virtual MessagerImp(){}
 20 };
 21 
 22 //平台实现 n
 23 class PCMessagerImp : public MessagerImp{
 24 public:
 25     
 26     virtual void PlaySound(){
 27         //**********
 28     }
 29     virtual void DrawShape(){
 30         //**********
 31     }
 32     virtual void WriteText(){
 33         //**********
 34     }
 35     virtual void Connect(){
 36         //**********
 37     }
 38 };
 39 
 40 class MobileMessagerImp : public MessagerImp{
 41 public:
 42     
 43     virtual void PlaySound(){
 44         //==========
 45     }
 46     virtual void DrawShape(){
 47         //==========
 48     }
 49     virtual void WriteText(){
 50         //==========
 51     }
 52     virtual void Connect(){
 53         //==========
 54     }
 55 };
 56 
 57 //业务抽象 m
 58 
 59 //类的数目:1+n+m
 60 
 61 class MessagerLite :public Messager {
 62 
 63     
 64 public:
 65     
 66     virtual void Login(string username, string password){
 67         
 68         messagerImp->Connect();
 69         //........
 70     }
 71     virtual void SendMessage(string message){
 72         
 73         messagerImp->WriteText();
 74         //........
 75     }
 76     virtual void SendPicture(Image image){
 77         
 78         messagerImp->DrawShape();
 79         //........
 80     }
 81 };
 82 
 83 class MessagerPerfect  :public Messager {
 84     
 85    
 86 public:
 87     
 88     virtual void Login(string username, string password){
 89         
 90         messagerImp->PlaySound();
 91         //********
 92         messagerImp->Connect();
 93         //........
 94     }
 95     virtual void SendMessage(string message){
 96         
 97         messagerImp->PlaySound();
 98         //********
 99         messagerImp->WriteText();
100         //........
101     }
102     virtual void SendPicture(Image image){
103         
104         messagerImp->PlaySound();
105         //********
106         messagerImp->DrawShape();
107         //........
108     }
109 };
110 
111 void Process(){
112     //运行时装配
113     MessagerImp* mImp=new PCMessagerImp();
114     Messager *m =new Messager(mImp);
115 }
View Code

示例2

  1 #include <string>
  2 #include <iostream>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 /**
  7  * The Implementation defines the interface for all implementation classes. It
  8  * doesn't have to match the Abstraction's interface. In fact, the two
  9  * interfaces can be entirely different. Typically the Implementation interface
 10  * provides only primitive operations, while the Abstraction defines higher-
 11  * level operations based on those primitives.
 12  */
 13 
 14 class Implementation {
 15  public:
 16   virtual ~Implementation() {}
 17   virtual std::string OperationImplementation() const = 0;
 18 };
 19 
 20 /**
 21  * Each Concrete Implementation corresponds to a specific platform and
 22  * implements the Implementation interface using that platform's API.
 23  */
 24 class ConcreteImplementationA : public Implementation {
 25  public:
 26   std::string OperationImplementation() const override {
 27     return "ConcreteImplementationA: Here's the result on the platform A.
";
 28   }
 29 };
 30 class ConcreteImplementationB : public Implementation {
 31  public:
 32   std::string OperationImplementation() const override {
 33     return "ConcreteImplementationB: Here's the result on the platform B.
";
 34   }
 35 };
 36 
 37 /**
 38  * The Abstraction defines the interface for the "control" part of the two class
 39  * hierarchies. It maintains a reference to an object of the Implementation
 40  * hierarchy and delegates all of the real work to this object.
 41  */
 42 
 43 class Abstraction {
 44   /**
 45    * @var Implementation
 46    */
 47  protected:
 48   Implementation* implementation_;
 49 
 50  public:
 51   Abstraction(Implementation* implementation) : implementation_(implementation) {
 52   }
 53 
 54   virtual ~Abstraction() {
 55   }
 56 
 57   virtual std::string Operation() const {
 58     return "Abstraction: Base operation with:
" +
 59            this->implementation_->OperationImplementation();
 60   }
 61 };
 62 /**
 63  * You can extend the Abstraction without changing the Implementation classes.
 64  */
 65 class ExtendedAbstraction : public Abstraction {
 66  public:
 67   ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
 68   }
 69   std::string Operation() const override {
 70     return "ExtendedAbstraction: Extended operation with:
" +
 71            this->implementation_->OperationImplementation();
 72   }
 73 };
 74 
 75 /**
 76  * Except for the initialization phase, where an Abstraction object gets linked
 77  * with a specific Implementation object, the client code should only depend on
 78  * the Abstraction class. This way the client code can support any abstraction-
 79  * implementation combination.
 80  */
 81 void ClientCode(const Abstraction& abstraction) {
 82   // ...
 83   std::cout << abstraction.Operation();
 84   // ...
 85 }
 86 /**
 87  * The client code should be able to work with any pre-configured abstraction-
 88  * implementation combination.
 89  */
 90 
 91 int main() {
 92   Implementation* implementation = new ConcreteImplementationA;
 93   Abstraction* abstraction = new Abstraction(implementation);
 94   ClientCode(*abstraction);
 95   std::cout << std::endl;
 96   delete implementation;
 97   delete abstraction;
 98 
 99   implementation = new ConcreteImplementationB;
100   abstraction = new ExtendedAbstraction(implementation);
101   ClientCode(*abstraction);
102 
103   delete implementation;
104   delete abstraction;
105 
106   return 0;
107 }
View Code

与其他模式关系

  • 桥接模式用于开发前期的设计,让程序的各个不同部分独立开发;适配器模式用于已有程序中,让不兼容的类实现合作
  • 桥接、状态、策略模式都基于组合模式,即将工作委派给其他对象
  • 可与抽象工厂搭配使用
  • 可与生成器搭配使用

参考

https://refactoringguru.cn/design-patterns/bridge

原文地址:https://www.cnblogs.com/cxc1357/p/12301328.html