zoukankan      html  css  js  c++  java
  • c++ 设计模式7 (Bridge 桥模式)

    4.2 Bridge 桥模式

    动机:

     由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度。

    代码示例:

    实现一个Messager,含有基本功能PlaySound,Connect等,并有PC、Mobile不同的平台实现 和 精简、完美等不同业务功能的版本

    实现方法1:

    Bridge1.cpp

    类的个数:1 + n + m*n,数量巨大且不同类之中有大量重复

    重构见方法2

      1 class Messager{
      2 public:
      3     virtual void Login(string username, string password)=0;
      4     virtual void SendMessage(string message)=0;
      5     virtual void SendPicture(Image image)=0;
      6 
      7     virtual void PlaySound()=0;
      8     virtual void DrawShape()=0;
      9     virtual void WriteText()=0;
     10     virtual void Connect()=0;
     11     
     12     virtual ~Messager(){}
     13 };
     14 
     15 
     16 //平台实现
     17 
     18 class PCMessagerBase : public Messager{
     19 public:
     20     
     21     virtual void PlaySound(){
     22         //**********
     23     }
     24     virtual void DrawShape(){
     25         //**********
     26     }
     27     virtual void WriteText(){
     28         //**********
     29     }
     30     virtual void Connect(){
     31         //**********
     32     }
     33 };
     34 
     35 class MobileMessagerBase : public Messager{
     36 public:
     37     
     38     virtual void PlaySound(){
     39         //==========
     40     }
     41     virtual void DrawShape(){
     42         //==========
     43     }
     44     virtual void WriteText(){
     45         //==========
     46     }
     47     virtual void Connect(){
     48         //==========
     49     }
     50 };
     51 
     52 
     53 
     54 //业务抽象
     55 
     56 class PCMessagerLite : public PCMessagerBase {
     57 public:
     58     
     59     virtual void Login(string username, string password){
     60         
     61         PCMessagerBase::Connect();
     62         //........
     63     }
     64     virtual void SendMessage(string message){
     65         
     66         PCMessagerBase::WriteText();
     67         //........
     68     }
     69     virtual void SendPicture(Image image){
     70         
     71         PCMessagerBase::DrawShape();
     72         //........
     73     }
     74 };
     75 
     76 
     77 
     78 class PCMessagerPerfect : public PCMessagerBase {
     79 public:
     80     
     81     virtual void Login(string username, string password){
     82         
     83         PCMessagerBase::PlaySound();
     84         //********
     85         PCMessagerBase::Connect();
     86         //........
     87     }
     88     virtual void SendMessage(string message){
     89         
     90         PCMessagerBase::PlaySound();
     91         //********
     92         PCMessagerBase::WriteText();
     93         //........
     94     }
     95     virtual void SendPicture(Image image){
     96         
     97         PCMessagerBase::PlaySound();
     98         //********
     99         PCMessagerBase::DrawShape();
    100         //........
    101     }
    102 };
    103 
    104 
    105 class MobileMessagerLite : public MobileMessagerBase {
    106 public:
    107     
    108     virtual void Login(string username, string password){
    109         
    110         MobileMessagerBase::Connect();
    111         //........
    112     }
    113     virtual void SendMessage(string message){
    114         
    115         MobileMessagerBase::WriteText();
    116         //........
    117     }
    118     virtual void SendPicture(Image image){
    119         
    120         MobileMessagerBase::DrawShape();
    121         //........
    122     }
    123 };
    124 
    125 
    126 class MobileMessagerPerfect : public MobileMessagerBase {
    127 public:
    128     
    129     virtual void Login(string username, string password){
    130         
    131         MobileMessagerBase::PlaySound();
    132         //********
    133         MobileMessagerBase::Connect();
    134         //........
    135     }
    136     virtual void SendMessage(string message){
    137         
    138         MobileMessagerBase::PlaySound();
    139         //********
    140         MobileMessagerBase::WriteText();
    141         //........
    142     }
    143     virtual void SendPicture(Image image){
    144         
    145         MobileMessagerBase::PlaySound();
    146         //********
    147         MobileMessagerBase::DrawShape();
    148         //........
    149     }
    150 };
    151 
    152 
    153 void Process(){
    154         //编译时装配
    155         Messager *m =
    156             new MobileMessagerPerfect();
    157 }

    重构步骤:

    1.继承转组合,将PCMessagerBase,Mobilemessager声明为字段;

     1 class PCMessagerLite  {
     2     PCMessagerBase *messager;
     3 public:
     4     
     5     virtual void Login(string username, string password){
     6         
     7         messager -> Connect();
     8         //........
     9     }
    10     virtual void SendMessage(string message){
    11         
    12         messager -> WriteText();
    13         //........
    14     }
    15     virtual void SendPicture(Image image){
    16         
    17         messager -> DrawShape();
    18         //........
    19     }
    20 };
    21 
    22 class PCMessagerLite  {
    23     MobileMessagerBase *messager;
    24 public:
    25     
    26     virtual void Login(string username, string password){
    27         
    28         messager -> Connect();
    29         //........
    30     }
    31     virtual void SendMessage(string message){
    32         
    33         messager -> WriteText();
    34         //........
    35     }
    36     virtual void SendPicture(Image image){
    37         
    38         messager -> DrawShape();
    39         //........
    40     }
    41 };

    2.观察上述两个类,发现只有 *messager 声明不同,故采用基类声明,运行时多态调用方式,创建不同的 PCMessagerBase,Mobilemessager;

     1 class PCMessagerLite  {
     2     Messager *messager; // = new PCMessagerBase()或 MobileMessagerBase()
     3 public:
     4     
     5     virtual void Login(string username, string password){
     6         
     7         messager -> Connect();
     8         //........
     9     }
    10     virtual void SendMessage(string message){
    11         
    12         messager -> WriteText();
    13         //........
    14     }
    15     virtual void SendPicture(Image image){
    16         
    17         messager -> DrawShape();
    18         //........
    19     }
    20 };        

    3.考虑步骤2的代码,Messager类是纯虚基类(抽象类),不能实例化,故= new ...不成立。

    分析产生这种状况的原因,是Login,SendPicture等与平台实现相关的方法,和PlaySound,DrawShape等与业务功能相关的方法不应该在一个类里。

    将其拆分,得到MessagerImp类。

    同时将MessagerLite,MessagerPerfect类中相同的MesseagerImp字段提到父类Messager,得到重构后的代码

    注意运行时装配

      1 class Messager{
      2 protected:
      3      MessagerImp* messagerImp;//...
      4 public:
      5     virtual void Login(string username, string password)=0;
      6     virtual void SendMessage(string message)=0;
      7     virtual void SendPicture(Image image)=0;
      8     
      9     virtual ~Messager(){}
     10 };
     11 
     12 class MessagerImp{
     13 public:
     14     virtual void PlaySound()=0;
     15     virtual void DrawShape()=0;
     16     virtual void WriteText()=0;
     17     virtual void Connect()=0;
     18     
     19     virtual MessagerImp(){}
     20 };
     21 
     22 
     23 //平台实现 n
     24 class PCMessagerImp : public MessagerImp{
     25 public:
     26     
     27     virtual void PlaySound(){
     28         //**********
     29     }
     30     virtual void DrawShape(){
     31         //**********
     32     }
     33     virtual void WriteText(){
     34         //**********
     35     }
     36     virtual void Connect(){
     37         //**********
     38     }
     39 };
     40 
     41 class MobileMessagerImp : public MessagerImp{
     42 public:
     43     
     44     virtual void PlaySound(){
     45         //==========
     46     }
     47     virtual void DrawShape(){
     48         //==========
     49     }
     50     virtual void WriteText(){
     51         //==========
     52     }
     53     virtual void Connect(){
     54         //==========
     55     }
     56 };
     57 
     58 
     59 
     60 //业务抽象 m
     61 
     62 //类的数目:1+n+m
     63 
     64 class MessagerLite :public Messager {
     65 
     66     
     67 public:
     68     
     69     virtual void Login(string username, string password){
     70         
     71         messagerImp->Connect();
     72         //........
     73     }
     74     virtual void SendMessage(string message){
     75         
     76         messagerImp->WriteText();
     77         //........
     78     }
     79     virtual void SendPicture(Image image){
     80         
     81         messagerImp->DrawShape();
     82         //........
     83     }
     84 };
     85 
     86 
     87 
     88 class MessagerPerfect  :public Messager {
     89     
     90    
     91 public:
     92     
     93     virtual void Login(string username, string password){
     94         
     95         messagerImp->PlaySound();
     96         //********
     97         messagerImp->Connect();
     98         //........
     99     }
    100     virtual void SendMessage(string message){
    101         
    102         messagerImp->PlaySound();
    103         //********
    104         messagerImp->WriteText();
    105         //........
    106     }
    107     virtual void SendPicture(Image image){
    108         
    109         messagerImp->PlaySound();
    110         //********
    111         messagerImp->DrawShape();
    112         //........
    113     }
    114 };
    115 
    116 
    117 
    118 
    119 void Process(){
    120     //运行时装配
    121     MessagerImp* mImp=new PCMessagerImp();
    122     Messager *m =new Messager(mImp);
    123 }

     模式定义:

    将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化。

    类图:

    要点总结:

    Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象的实现可以沿着各自的维度来变化。所谓抽象和实现研制各自维度的变化,即“子类化”他们。

    Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个雷只有一个变化的原因),复用性较差。Bridge模式是比多继承更好的解决方案。

    Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也有多余两个的变化维度,这是可以使用Bridge的扩展模式。

  • 相关阅读:
    UVa532 Dungeon Master 三维迷宫
    6.4.2 走迷宫
    UVA 439 Knight Moves
    UVa784 Maze Exploration
    UVa657 The die is cast
    UVa572 Oil Deposits DFS求连通块
    UVa10562 Undraw the Trees
    UVa839 Not so Mobile
    327
    UVa699 The Falling Leaves
  • 原文地址:https://www.cnblogs.com/wangxiaobao/p/5208448.html
Copyright © 2011-2022 走看看