首页 > 代码库 > c++ 设计模式7 (Bridge 桥模式)

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

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的扩展模式。

 

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