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

时间: 2024-10-12 22:08:24

c++ 设计模式7 (Bridge 桥模式)的相关文章

设计模式(7)--Bridge(桥接模式)--结构型

1.模式定义: 桥接模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式.桥接模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化”. 2.模式特点: 桥接模式虽然不是一个使用频率很高的模式,但是熟悉这个模式对于理解面向对象的设计原则,包括“开-闭”原则以及组合/聚合复用原则都很有帮助.理解好这两个原则,有助于形成正确的设计思想和培养良好的设计风格. 桥接模式的用意是“将抽象化(Ab

设计模式(十二)桥模式(Bridge)-结构型

桥模式Bridge引文 根据面向对象的设计原则,应该尽量使用组合而不是继承.桥模式将抽象与其实现解耦,使他们可以分别独立地变化,是继承的一种代替方式. 对于两个类之间需要进行关联时,不要直接在一个类的代码中调用另一个类的代码,而是要通过这些设计模式,在两个类之间建立一个类似的缓冲器的类,从而将直接关联的两个类进行解耦,以保证以后当一个类的接口发生变化时不会影响另一个类的使用. 实现原理图 桥模式实现原理图 桥模式试讲抽象和实现分离实现解耦,使他们可以分别独立地变化.桥模式也是继承关系的一个替代方

设计模式的征途—8.桥接(Bridge)模式

在现实生活中,我们常常会用到两种或多种类型的笔,比如毛笔和蜡笔.假设我们需要大.中.小三种类型的画笔来绘制12中不同的颜色,如果我们使用蜡笔,需要准备3*12=36支.但如果使用毛笔的话,只需要提供3种型号的毛笔,外加12个颜料盒即可,涉及的对象个数仅为3+12=15,远远小于36却能实现与36支蜡笔同样的功能.如果需要新增一种画笔,并且同样需要12种颜色,那么蜡笔需要增加12支,而毛笔却只需要新增1支.通过分析,在蜡笔中,颜色和型号两个不同的变化维度耦合在一起,无论对其中任何一个维度进行扩展,

设计模式(八):Bridge桥接模式 -- 结构型模式

1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度? 例子1:设想如果要绘制矩形.圆形.椭圆.正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色.绿色.蓝色等,此时至少有如下两种设计方案: •第一种设计方案是为每一种形状都提供一套各种颜色的版本. •第二种设计方案是根据实际需要对形状和颜色进行组合. 方案1: 方案2:  

Java设计模式——桥模式

概述 桥模式(Bridge)是为了解决将抽象部分与实现部分分离,好让他们都在自己的维度上有多维度地变化.这句话是好理解的,只是我在学习完桥模式之后,存在一些疑问,还好现在想通了.现在我就桥模式的设计思想和我的疑问一并发出,希望于你有益. 版权说明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 本文作者:Coding-Naga 发表日期: 2016年3月31日 本文链接:http://blog.csdn.net/lemon_tree12138/article/detail

Bridge Design Pattern (桥模式)

桥模式的核心思想在于:抽象和行为分离. 在JDON里面,板桥里人举的例子是咖啡(抽象)与加奶(行为)的关系.原文(http://www.jdon.com/designpatterns/bridge.htm) 意思比较清晰,比如说,按照排列组合关系,大杯咖啡,小杯咖啡,和是否加奶,能够组成四种组合:大杯加奶,小杯加奶,大杯不加奶,小杯不加奶,如果再加一种行为进去,比如加巧克力,或者加方糖什么的,势必会出现更多的组合.如果为每一种组合创造一种对象,会造成对象过多代码混乱的状况. 还有很多例子阐述类似

Java桥模式(Bridge模式)

Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合. 为什么使用桥模式 通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以下两种: 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩:这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了. 实际应用上,常常有可能在这多个concrete class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同

Design Pattern Bridge 桥设计模式

桥设计模式其实就是一个简单的has a relationship,就是一个类拥有另一个类,并使用另一个类实现需要的功能. 比如遥控器和电视之间可以使用桥设计模式达到可以使用同一个遥控器控制多台电视机的目的. 这样的设计思想是多种设计模式反反复复使用基本思想. 仔细思考下会发现多种设计模式的底层思想其实是相通的,不过具体实现或者某些细节,应用等有那么一点差别罢了. 下面就实现一个TV和remoter类,其中的remoter是可以随时更换的. #include <stdio.h> class Re

设计模式入门之桥接模式Bridge

//桥接模式定义:将抽象部分与它的实现部分分离,使得他们都可以独立地变化 //广义来讲,桥接模式非常普遍,面向抽象编程,面向接口编程就可以看作是他的体现 //实例:一个系统,要按照不同的要求发信息(普通,加急,特急),而且还要以不同的方式发送(站内信,Email,短信)等,考虑到其扩展性,用桥接模式再合适不过了 //上代码 //桥接的一半---抽象部分 public abstract class AbstractionMessage { protected MessageImplementor