桥接模式简介:
将抽象部分和实现部分分离,抽象部分的变化无关实现,实现部分的变化也无需通知抽象部分。例如假设一个类有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 ", 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 请按任意键继续. . .