面向对象设计模式之Bridge桥接模式(结构型)

问题分析:假如我们需要开发一个同时支持PC和手机的坦克游戏,游戏在PC和手机上功能都一样,都有同样的类型,面临同样的功能需求变化,比如坦克可能有多种不同的型号:T50,T75,T90..对于其中的坦克设计,我们可能很容易设计出来一个Tank的抽象类,然后各种不同型号的Tank继承自该类,但是PC和手机上的图形绘制、声效、操作等实现完全不同...因此对于各种型号的坦克,都 要提供各种不同平台上的坦克实现;而这样的设计带来了很多问题:有很多重复代码,类的结构过于复杂,难以维护,最致命的是引入任何新的平台,比如TV上的Tank游戏,都会让整个类层次级结构复杂化

动机:思考上述问题的症结,事实上由于Tank类型的固有逻辑,使得Tank类型具有了两个变化的维度——一个变化的维度为“平台的变化”,一个变化的维度为“型号的变化”;如何应对这种“多维度的变化”?如何利用面向对象技术使得Tank类型可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度
意图:将抽象部分和实现部分分离(将一个事物中多个维度的变化分离),使它们可以独立的变化 即将不同纬度的变化抽象出来,并子类化它们,用对象组合的方式实现应对其变化

可适用性:

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时B r i d g e 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
  • (C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
  • 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。R u m b a u g h 称这种类层次结构为“嵌套的普化”(nested generalizations )。
  • 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是C o p l i e n 的S t r i n g 类[ C o p 9 2 ],在这个类中多个对象可以共享同一个字符串表示(S t r i n g R e p )。

    UML图解:

    示例代码:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 
      6 /***
      7  * 没有使用桥接模式之前的设计实现代码
      8  * ***/
      9 namespace Bridge
     10 {
     11 
     12     public abstract  class Tank
     13     {
     14         public abstract void Run();
     15         public abstract void Shot();
     16         public abstract void Stop();
     17     }
     18 
     19     public class T50 : Tank
     20     {
     21 
     22         public override void Run()
     23         {
     24             //....
     25         }
     26 
     27         public override void Shot()
     28         {
     29             //....
     30         }
     31 
     32         public override void Stop()
     33         {
     34             //....
     35         }
     36     }
     37     public class PCT50 : T50
     38     {
     39         public override void Run()
     40         {
     41             //....
     42         }
     43 
     44         public override void Shot()
     45         {
     46             //....
     47         }
     48 
     49         public override void Stop()
     50         {
     51             //....
     52         }
     53     }
     54     public class MobileT50 : T50
     55     {
     56         public override void Run()
     57         {
     58             //....
     59         }
     60 
     61         public override void Shot()
     62         {
     63             //....
     64         }
     65 
     66         public override void Stop()
     67         {
     68             //....
     69         }
     70     }
     71     public class TVT50 : T50
     72     {
     73         public override void Run()
     74         {
     75             //....
     76         }
     77 
     78         public override void Shot()
     79         {
     80             //....
     81         }
     82 
     83         public override void Stop()
     84         {
     85             //....
     86         }
     87     }
     88 
     89 
     90 
     91     public class T75 : Tank
     92     {
     93 
     94         public override void Run()
     95         {
     96             //....
     97         }
     98 
     99         public override void Shot()
    100         {
    101             //....
    102         }
    103 
    104         public override void Stop()
    105         {
    106             //....
    107         }
    108     }
    109     public class PCT75 : T75
    110     {
    111         public override void Run()
    112         {
    113             //....
    114         }
    115 
    116         public override void Shot()
    117         {
    118             //....
    119         }
    120 
    121         public override void Stop()
    122         {
    123             //....
    124         }
    125     }
    126     public class MobileT75 : T75
    127     {
    128         public override void Run()
    129         {
    130             //....
    131         }
    132 
    133         public override void Shot()
    134         {
    135             //....
    136         }
    137 
    138         public override void Stop()
    139         {
    140             //....
    141         }
    142     }
    143     public class TVT75 : T75
    144     {
    145         public override void Run()
    146         {
    147             //....
    148         }
    149 
    150         public override void Shot()
    151         {
    152             //....
    153         }
    154 
    155         public override void Stop()
    156         {
    157             //....
    158         }
    159     }
    160 
    161     public class T90 : Tank
    162     {
    163 
    164         public override void Run()
    165         {
    166             //....
    167         }
    168 
    169         public override void Shot()
    170         {
    171             //....
    172         }
    173 
    174         public override void Stop()
    175         {
    176             //....
    177         }
    178     }
    179     public class PCT90 : T90
    180     {
    181         public override void Run()
    182         {
    183             //....
    184         }
    185 
    186         public override void Shot()
    187         {
    188             //....
    189         }
    190 
    191         public override void Stop()
    192         {
    193             //....
    194         }
    195     }
    196     public class MobileT90 : T90
    197     {
    198         public override void Run()
    199         {
    200             //....
    201         }
    202 
    203         public override void Shot()
    204         {
    205             //....
    206         }
    207 
    208         public override void Stop()
    209         {
    210             //....
    211         }
    212     }
    213     public class TVT90 : T90
    214     {
    215         public override void Run()
    216         {
    217             //....
    218         }
    219 
    220         public override void Shot()
    221         {
    222             //....
    223         }
    224 
    225         public override void Stop()
    226         {
    227             //....
    228         }
    229     }
    230 
    231     /***
    232      * 实现的缺点:子类繁衍多,不能应对变化
    233      * ***/
    234 }using System;
    235 using System.Collections.Generic;
    236 using System.Linq;
    237 using System.Text;
    238 
    239 /***
    240  * 使用Bridge模式后的代码实现
    241  * ***/
    242 namespace Bridge
    243 {
    244     /// <summary>
    245     /// 将不同平台坦克实现抽象出来(应对平台变化)
    246     /// </summary>
    247     public abstract class TankPlatformImplementation
    248     {
    249         public abstract void MoveTo();
    250         public abstract void Draw();
    251         public abstract void Stop();
    252     }
    253 
    254     /// <summary>
    255     /// PC平台的Tank
    256     /// </summary>
    257     public class PCTankImplementation:TankPlatformImplementation
    258     {
    259 
    260          public override void  MoveTo()
    261          {
    262             //PC上的实现代码
    263          }
    264 
    265          public override void  Draw()
    266          {
    267            //PC上的实现代码
    268          }
    269 
    270          public override void  Stop()
    271          {
    272             //PC上的实现代码
    273          }
    274     }
    275 
    276     /// <summary>
    277     /// Mobile平台的Tank
    278     /// </summary>
    279     public class MobileTankImplementation:TankPlatformImplementation
    280     {
    281 
    282          public override void  MoveTo()
    283          {
    284            // Mobile上的实现代码
    285          }
    286 
    287          public override void  Draw()
    288          {
    289            // Mobile上的实现代码
    290          }
    291 
    292          public override void  Stop()
    293          {
    294             // Mobile上的实现代码
    295          }
    296     }
    297 
    298     /// <summary>
    299     /// 坦克抽象类(应对坦克型号的变化)
    300     /// </summary>
    301     public abstract class Tank
    302     {
    303         TankPlatformImplementation tanklmp;//对象组合
    304         public Tank( TankPlatformImplementation tanklmp)
    305         {
    306             this.tanklmp = tanklmp;
    307         }
    308         public abstract void Run();
    309         public abstract void Shot();
    310         public abstract void Stop();
    311     }
    312 
    313     public class T50 : Tank
    314     {
    315         public T50(TankPlatformImplementation tanklmp)
    316             : base(tanklmp)
    317         { 
    318            
    319         }
    320 
    321         public override void Run()
    322         {
    323             //....
    324             //using tanklmp do something...
    325             //...
    326         }
    327 
    328         public override void Shot()
    329         {
    330             //....
    331             //using tanklmp do something...
    332             //...
    333         }
    334 
    335         public override void Stop()
    336         {
    337             //....
    338             //using tanklmp do something...
    339             //...
    340         }
    341     }
    342 
    343     public class T75 : Tank
    344     {
    345         public T75(TankPlatformImplementation tanklmp)
    346             : base(tanklmp)
    347         {
    348 
    349         }
    350 
    351         public override void Run()
    352         {
    353             //....
    354             //using tanklmp do something...
    355             //...
    356         }
    357 
    358         public override void Shot()
    359         {
    360             //....
    361             //using tanklmp do something...
    362             //...
    363         }
    364 
    365         public override void Stop()
    366         {
    367             //....
    368             //using tanklmp do something...
    369             //...
    370         }
    371     }
    372 
    373     public class App
    374     {
    375         public static void Main()
    376         {
    377            //手机平台游戏
    378             TankPlatformImplementation mobileTank=new MobileTankImplementation();
    379             Tank tank=new T50(mobileTank);
    380             //tank.Shot();
    381         }
    382     }
    383 }

    注:本示例代码是本人学习Webcast C#面向对象设计模式纵横谈系列讲座视频时,跟着李建忠老师一步一步的编写的,在此奉献出来,仅供大家参考

作者:JumpByte
来源:http://www.cnblogs.com/yja9010
更新: http://jumpbyte.cn
声明:本博客原创文字只代表本人的观点或结论,于网站他人无关,非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
原文地址:https://www.cnblogs.com/yja9010/p/3178773.html