c++ 设计模式7 (Bridge 桥模式)

来源:互联网 发布:重大电气知乎 编辑:程序博客网 时间:2024/06/05 03:00

4.2 Bridge 桥模式

动机:

 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度。

 

代码示例:

实现一个Messager,含有基本功能PlaySound,Connect等,并有PC、Mobile不同的平台实现 和 精简、完美等不同业务功能的版本

实现方法1:

Bridge1.cpp

类的个数:1 + n + m*n,数量巨大且不同类之中有大量重复

重构见方法2

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

 

重构步骤:

1.继承转组合,将PCMessagerBase,Mobilemessager声明为字段;

复制代码
 1 class PCMessagerLite  { 2     PCMessagerBase *messager; 3 public: 4      5     virtual void Login(string username, string password){ 6          7         messager -> Connect(); 8         //........ 9     }10     virtual void SendMessage(string message){11         12         messager -> WriteText();13         //........14     }15     virtual void SendPicture(Image image){16         17         messager -> DrawShape();18         //........19     }20 };21 22 class PCMessagerLite  {23     MobileMessagerBase *messager;24 public:25     26     virtual void Login(string username, string password){27         28         messager -> Connect();29         //........30     }31     virtual void SendMessage(string message){32         33         messager -> WriteText();34         //........35     }36     virtual void SendPicture(Image image){37         38         messager -> DrawShape();39         //........40     }41 };
复制代码

2.观察上述两个类,发现只有 *messager 声明不同,故采用基类声明,运行时多态调用方式,创建不同的 PCMessagerBase,Mobilemessager;

复制代码
 1 class PCMessagerLite  { 2     Messager *messager; // = new PCMessagerBase()或 MobileMessagerBase() 3 public: 4      5     virtual void Login(string username, string password){ 6          7         messager -> Connect(); 8         //........ 9     }10     virtual void SendMessage(string message){11         12         messager -> WriteText();13         //........14     }15     virtual void SendPicture(Image image){16         17         messager -> DrawShape();18         //........19     }20 };        
复制代码

3.考虑步骤2的代码,Messager类是纯虚基类(抽象类),不能实例化,故= new ...不成立。

分析产生这种状况的原因,是Login,SendPicture等与平台实现相关的方法,和PlaySound,DrawShape等与业务功能相关的方法不应该在一个类里。

将其拆分,得到MessagerImp类。

同时将MessagerLite,MessagerPerfect类中相同的MesseagerImp字段提到父类Messager,得到重构后的代码

注意运行时装配

复制代码
  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  23 //平台实现 n 24 class PCMessagerImp : public MessagerImp{ 25 public: 26      27     virtual void PlaySound(){ 28         //********** 29     } 30     virtual void DrawShape(){ 31         //********** 32     } 33     virtual void WriteText(){ 34         //********** 35     } 36     virtual void Connect(){ 37         //********** 38     } 39 }; 40  41 class MobileMessagerImp : public MessagerImp{ 42 public: 43      44     virtual void PlaySound(){ 45         //========== 46     } 47     virtual void DrawShape(){ 48         //========== 49     } 50     virtual void WriteText(){ 51         //========== 52     } 53     virtual void Connect(){ 54         //========== 55     } 56 }; 57  58  59  60 //业务抽象 m 61  62 //类的数目:1+n+m 63  64 class MessagerLite :public Messager { 65  66      67 public: 68      69     virtual void Login(string username, string password){ 70          71         messagerImp->Connect(); 72         //........ 73     } 74     virtual void SendMessage(string message){ 75          76         messagerImp->WriteText(); 77         //........ 78     } 79     virtual void SendPicture(Image image){ 80          81         messagerImp->DrawShape(); 82         //........ 83     } 84 }; 85  86  87  88 class MessagerPerfect  :public Messager { 89      90     91 public: 92      93     virtual void Login(string username, string password){ 94          95         messagerImp->PlaySound(); 96         //******** 97         messagerImp->Connect(); 98         //........ 99     }100     virtual void SendMessage(string message){101         102         messagerImp->PlaySound();103         //********104         messagerImp->WriteText();105         //........106     }107     virtual void SendPicture(Image image){108         109         messagerImp->PlaySound();110         //********111         messagerImp->DrawShape();112         //........113     }114 };115 116 117 118 119 void Process(){120     //运行时装配121     MessagerImp* mImp=new PCMessagerImp();122     Messager *m =new Messager(mImp);123 }
复制代码

 模式定义:

将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化。

类图:

要点总结:

Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象的实现可以沿着各自的维度来变化。所谓抽象和实现研制各自维度的变化,即“子类化”他们。

Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个雷只有一个变化的原因),复用性较差。Bridge模式是比多继承更好的解决方案。

Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也有多余两个的变化维度,这是可以使用Bridge的扩展模式。

 

原创粉丝点击