學習設計模式系列之四:橋接模式

橋接模式簡介:設計模式

將抽象部分和實現部分分離,抽象部分的變化無關實現,實現部分的變化也無需通知抽象部分。例如假設一個類有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
請按任意鍵繼續. . .
相關文章
相關標籤/搜索