zoukankan      html  css  js  c++  java
  • GOF之桥接模式

    引入问题:

    假如我们需要开发一个同事支持PC和手机的坦克游戏,游戏在PC和手机上功能都一样,都有同样的类型,面临同样的功能需求变化,比如坦克可能有多种不同的型号:T50,T75,T90...

    但是PC和手机上的图形绘制、声效、操作等实现完全不同...因此对于各种型号的坦克,都要提供不同平台上的坦克实现。

    动机(Motivation)

    思考上述问题的症结:事实上由于Tank类型的固有逻辑,使得Tank类型具有了两个变化的维度---一个变化的维度为“平台的变化”,一个变化的维度为“型号的变化”。

    如何应对这种“多维度的变化”?如何利用面向对象技术来使得Tank类型可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度?

    意图(Intent)

    将抽象部分与实现部分分离,使它们都可以独立的变化。

    结构(Structure)

    代码实现:

     1 一种维度的变化
     2  public abstract class TankPlatformImplementation
     3     {
     4         public abstract void MoveTo();
     5         public abstract void DrawTank();
     6         public abstract void DoShot();
     7     }
     8 
     9     public class PCTankImplementation : TankPlatformImplementation
    10     {
    11 
    12         public override void MoveTo()
    13         {
    14             Console.WriteLine("PC端移动");
    15         }
    16 
    17         public override void DrawTank()
    18         {
    19             Console.WriteLine("PC端画坦克");
    20         }
    21 
    22         public override void DoShot()
    23         {
    24             Console.WriteLine("PC端攻击");
    25         }
    26     }
    27 
    28     public class MobileTankImplementation : TankPlatformImplementation
    29     {
    30 
    31         public override void MoveTo()
    32         {
    33             Console.WriteLine("移动端移动");
    34         }
    35 
    36         public override void DrawTank()
    37         {
    38             Console.WriteLine("移动端画坦克");
    39         }
    40 
    41         public override void DoShot()
    42         {
    43             Console.WriteLine("移动端攻击");
    44         }
    45     }
      1 另一种维度的变化
      2  public abstract class Tank
      3     {
      4         protected TankPlatformImplementation tpimp;
      5         public abstract void Run();
      6         public abstract void Stop();
      7     }
      8 
      9     public class T50 : Tank
     10     {
     11         public T50(TankPlatformImplementation tpimp)
     12         {
     13             this.tpimp = tpimp;
     14         }
     15         public void MoveTo()
     16         {
     17             Console.Write("T50的");
     18             tpimp.MoveTo();            
     19         }
     20         public void DoShot()
     21         {
     22             Console.Write("T50的");
     23             tpimp.DoShot();
     24         }
     25         public void DrawTank()
     26         {
     27             Console.Write("T50的");
     28             tpimp.DrawTank();
     29         }
     30 
     31 
     32         public override void Run()
     33         {
     34             Console.WriteLine("T50跑");
     35         }
     36 
     37         public override void Stop()
     38         {
     39             Console.WriteLine("T50停");
     40         }
     41     }
     42     public class T75 : Tank
     43     {
     44     public T75(TankPlatformImplementation tpimp)
     45         {
     46             this.tpimp = tpimp;
     47         }
     48         public void MoveTo()
     49         {
     50             Console.Write("T75的");
     51             tpimp.MoveTo();
     52         }
     53         public void DoShot()
     54         {
     55             Console.Write("T75的");
     56             tpimp.DoShot();
     57         }
     58         public void DrawTank()
     59         {
     60             Console.Write("T75的");
     61             tpimp.DrawTank();
     62         }
     63 
     64         public override void Run()
     65         {
     66             Console.WriteLine("T75跑");
     67         }
     68 
     69         public override void Stop()
     70         {
     71             Console.WriteLine("T75停");
     72         }
     73     }
     74     public class T90 : Tank
     75     { 
     76     public T90(TankPlatformImplementation tpimp)
     77         {           
     78             this.tpimp = tpimp;
     79         }
     80         public void MoveTo()
     81         {
     82             Console.Write("T90的");
     83             tpimp.MoveTo();
     84         }
     85         public void DoShot()
     86         {
     87             Console.Write("T90的");
     88             tpimp.DoShot();
     89         }
     90         public void DrawTank()
     91         {
     92             Console.Write("T90的");
     93             tpimp.DrawTank();
     94         }
     95 
     96         public override void Run()
     97         {
     98             Console.WriteLine("T90跑");
     99         }
    100 
    101         public override void Stop()
    102         {
    103             Console.WriteLine("T90停");
    104         }
    105     }
     1 主函数的调用
     2  static void Main(string[] args)
     3         {
     4             T75 tank = new T75(new MobileTankImplementation());
     5             tank.DrawTank();
     6             tank.DoShot();
     7             tank.MoveTo();
     8             tank.Run();
     9             tank.Stop();
    10             Console.ReadKey();
    11         }

    Bridge模式的几个要点:

    Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象(Tank的型号)和实现(不同的平台)可以沿着各自的维度来变化。

    所谓抽象和实现沿着各自的维度的变化,即“子类化”它们,比如不同的Tank型号子类,和不同的平台子类。得到各个子类之后,便可以任意组合它们,从而获得 不同平台上的不同型号。

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

    Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈--换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

  • 相关阅读:
    浅议APC
    fastIO
    设备对象 驱动对象
    PostMessage和SendMessage的区别
    使用DLL在进程间共享数据
    32位程序读写64位程序内存
    windows文件映射
    windows消息传送(自定义消息和WM_COPYDATA)
    windows剪贴板
    mysql innobackupex备份工具
  • 原文地址:https://www.cnblogs.com/pushudepu/p/6037796.html
Copyright © 2011-2022 走看看