学习设计模式系列之四:桥接模式

桥接模式简介:

将抽象部分和实现部分分离,抽象部分的变化无关实现,实现部分的变化也无需通知抽象部分。例如假设一个类有M中抽象子类,实现有N中实现方法,不使用桥接模式的复杂度为O(M×N),而使用桥接模式,对类进行抽象/实现层次划分,之后分别进行抽象类派生和实现方法派生,复杂度为O(M+N)。

核心:

         极类似于网络中层次的划分,应用层不需要考虑链路设计,上层协议调用下层协议,下层协议为上层协议服务。

问题多维,可划分层次;

应用层:抽象层;底层:实现层。

难点:

划分层次:抽象层和实现层,抽象层调用实现层,实现层可以独立设计

区别:(个人认为使用顺序应该是:结构型设计模式->创建型设计模型->行为型设计模式)

结构型模式:关于类与类之间的依赖、关联、聚合、泛化、实现关系。

创建型模式:关于对象的构造方法,在类图已确定的情况下,去设计构造对象的方法。

行为型模式:关于程序运行的流程,独立设计运行、业务处理逻辑的类,无关实体类。

举例:

客户端程序界面绘制系统的设计。

问题划分:

风格主题皮肤

界面模块

炫紫神话

底比斯之水

土豪金

标题(背景/字体/字号/颜色)

1

2

3

正文(字体/字号/颜色)

4

5

6

按钮(图标)

7

8

9

表 1 问题划分表

从表格可知:一共有3×3=9种绘制方式,如果不使用桥接设计模式,界面类需要为每一种为每一款主题都设计具体实现方法:

 

图 1 不使用桥接模式

如果使用桥接设计模式:将具体的绘制方法和界面模块分离:

 

图 2 使用桥接模式

代码:

  1 #include <stdlib.h>
  2 
  3 /***
  4 * @author:zanzan101
  5 */
  6 
  7 inline void P(const char* str)
  8 {
  9     printf("%s\n", str);
 10 }
 11 
 12 // 消息处理模块
 13 class MessageHandling
 14 {
 15     //
 16 };
 17 
 18 // 设备上下文
 19 class DeviceContext
 20 {
 21     //
 22 };
 23 
 24 // 界面绘制类
 25 class UIRender
 26 {
 27 public:
 28     virtual void draw_background(DeviceContext* pdc) = 0;
 29     virtual void draw_line(DeviceContext* pdc) = 0;
 30     virtual void draw_icon(DeviceContext* pdc) = 0;
 31     virtual void draw_text(DeviceContext* pdc) = 0;
 32 };
 33 
 34 // 界面绘制实现类
 35 class UIRenderStyleA: public UIRender
 36 {
 37 public:
 38     void draw_background(DeviceContext* pdc){P("draw back with style A");};
 39     void draw_line(DeviceContext* pdc){P("draw line with style A");};
 40     void draw_icon(DeviceContext* pdc){P("draw icon with style A");};
 41     void draw_text(DeviceContext* pdc){P("draw text with style A");};
 42 };
 43 class UIRenderStyleB: public UIRender
 44 {
 45 public:
 46     void draw_background(DeviceContext* pdc){P("draw back with style B");};
 47     void draw_line(DeviceContext* pdc){P("draw line with style B");};
 48     void draw_icon(DeviceContext* pdc){P("draw icon with style B");};
 49     void draw_text(DeviceContext* pdc){P("draw text with style B");};
 50 };
 51 class UIRenderStyleC: public UIRender
 52 {
 53 public:
 54     void draw_background(DeviceContext* pdc){P("draw back with style C");};
 55     void draw_line(DeviceContext* pdc){P("draw line with style C");};
 56     void draw_icon(DeviceContext* pdc){P("draw icon with style C");};
 57     void draw_text(DeviceContext* pdc){P("draw text with style C");};
 58 };
 59 
 60 // 界面控件基类
 61 class UIWindow
 62 {
 63 private:
 64     MessageHandling* _mh;
 65     DeviceContext* _dc;
 66     UIRender* _ur;
 67 protected:
 68     void background() const {_ur->draw_background(_dc);};
 69     void line() const {_ur->draw_line(_dc);}
 70     void icon() const {_ur->draw_icon(_dc);}
 71     void text() const {_ur->draw_text(_dc);}
 72     virtual void on_paint() const = 0;
 73 public:
 74     UIWindow(MessageHandling* m, DeviceContext* d, UIRender* r): _mh(m), _dc(d), _ur(r){}
 75     void set_render(UIRender* r)
 76     {
 77         if(_ur)
 78             delete _ur;
 79         _ur = r;
 80     }
 81 };
 82 
 83 // 界面控件子类
 84 class UITitle: public UIWindow
 85 {
 86 public:
 87     UITitle(MessageHandling* m, DeviceContext* d, UIRender* r): UIWindow(m, d, r){}
 88 
 89     // 注意:如果基类中有const修饰函数,子类实现该函数时,必须加const修饰,否则视为重载,不视为覆盖
 90     void on_paint() const    
 91     {
 92         // 调用底层的绘制方法:line、background等等
 93         background();
 94         line();
 95         text();
 96         line();
 97         // ...
 98     }
 99 };
100 class UIText: public UIWindow
101 {
102 public:
103     UIText(MessageHandling* m, DeviceContext* d, UIRender* r): UIWindow(m, d, r){}
104     void on_paint() const
105     {
106         // ...
107         // ...
108     }
109 };
110 class UIButton: public UIWindow
111 {
112 public:
113     UIButton(MessageHandling* m, DeviceContext* d, UIRender* r): UIWindow(m, d, r){}
114     void on_paint() const
115     {
116         // ...
117         // ...
118     }
119 };
120 
121 
122 int _tmain(int argc, _TCHAR* argv[])
123 {
124     MessageHandling mh;
125     DeviceContext dc;
126     P(">> use style A:");
127     UITitle title(&mh, &dc, new UIRenderStyleA());
128     title.on_paint();
129 
130     P(">> switch to style B");
131     title.set_render(new UIRenderStyleB());
132     title.on_paint();
133 
134     P(">> switch to style C");
135     title.set_render(new UIRenderStyleC());
136     title.on_paint();
137 
138     system("pause");
139     return 0;
140 }

输出结果:

>> use style A:
draw back with style A
draw line with style A
draw text with style A
draw line with style A
>> switch to style B
draw back with style B
draw line with style B
draw text with style B
draw line with style B
>> switch to style C
draw back with style C
draw line with style C
draw text with style C
draw line with style C
请按任意键继续. . .

 

 

posted @ 2013-11-03 21:04  铁甲小宝  阅读(207)  评论(0编辑  收藏  举报