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


    桥接模式简介:

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

     

  • 相关阅读:
    浅谈数据分析中的“暗物质”
    浅谈数据分析中的“暗物质”
    房屋价格数据采集与分析
    房屋价格数据采集与分析
    基于Python对象引用、可变性和垃圾回收详解
    基于Python对象引用、可变性和垃圾回收详解
    人脸识别中常用的几种分类器
    人脸识别中常用的几种分类器
    解析新零售,互联网大数据时代的到来
    osg::NodeVisitor中计算一个节点对应的世界变换矩阵、法向量、顶点坐标
  • 原文地址:https://www.cnblogs.com/zanzan101/p/3405433.html
Copyright © 2020-2023  润新知