zoukankan      html  css  js  c++  java
  • 面向对象设计模式之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
    声明:本博客原创文字只代表本人的观点或结论,于网站他人无关,非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/yja9010/p/3178773.html
Copyright © 2011-2022 走看看