橋接模式簡介:設計模式
將抽象部分和實現部分分離,抽象部分的變化無關實現,實現部分的變化也無需通知抽象部分。例如假設一個類有M中抽象子類,實現有N中實現方法,不使用橋接模式的複雜度爲O(M×N),而使用橋接模式,對類進行抽象/實現層次劃分,以後分別進行抽象類派生和實現方法派生,複雜度爲O(M+N)。網絡
核心:函數
極相似於網絡中層次的劃分,應用層不須要考慮鏈路設計,上層協議調用下層協議,下層協議爲上層協議服務。字體
問題多維,可劃分層次;spa
應用層:抽象層;底層:實現層。設計
難點:code
劃分層次:抽象層和實現層,抽象層調用實現層,實現層能夠獨立設計對象
區別:(我的認爲使用順序應該是:結構型設計模式->建立型設計模型->行爲型設計模式)blog
結構型模式:關於類與類之間的依賴、關聯、聚合、泛化、實現關係。ci
建立型模式:關於對象的構造方法,在類圖已肯定的狀況下,去設計構造對象的方法。
行爲型模式:關於程序運行的流程,獨立設計運行、業務處理邏輯的類,無關實體類。
舉例:
客戶端程序界面繪製系統的設計。
問題劃分:
風格主題皮膚 界面模塊 |
炫紫神話 |
底比斯之水 |
土豪金 |
標題(背景/字體/字號/顏色) |
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 請按任意鍵繼續. . .