深入解析C#设计模式中对桥接模式的具体运用

作者:TerryLee 时间:2023-11-08 21:53:06 

这里以电视遥控器的一个例子来引出桥接模式解决的问题,首先,我们每个牌子的电视机都有一个遥控器,此时我们能想到的一个设计是——把遥控器做为一个抽象类,抽象类中提供遥控器的所有实现,其他具体电视品牌的遥控器都继承这个抽象类,具体设计类图如下:

深入解析C#设计模式中对桥接模式的具体运用

这样的实现使得每部不同型号的电视都有自己遥控器实现,这样的设计对于电视机的改变可以很好地应对,只需要添加一个派生类就搞定了,但随着时间的推移,用户需要改变遥控器的功能,如:用户可能后面需要对遥控器添加返回上一个台等功能时,此时上面的设计就需要修改抽象类RemoteControl的提供的接口了,此时可能只需要向抽象类中添加一个方法就可以解决了,但是这样带来的问题是我们改变了抽象的实现,如果用户需要同时改变电视机品型号和遥控器功能时,上面的设计就会导致相当大的修改,显然这样的设计并不是好的设计。然而使用桥接模式可以很好地解决这个问题,下面让我具体看看桥接模式是如何实现的。

定义
桥接模式即将抽象部分与实现部分脱耦,使它们可以独立变化。对于上面的问题中,抽象化也就是RemoteControl类,实现部分也就是On()、Off()、NextChannel()等这样的方法(即遥控器的实现),上面的设计中,抽象化和实现部分在一起,桥接模式的目的就是使两者分离,根据面向对象的封装变化的原则,我们可以把实现部分的变化(也就是遥控器功能的变化)封装到另外一个类中,这样的一个思路也就是桥接模式的实现,大家可以对照桥接模式的实现代码来解决我们的分析思路。

桥接模式实现
上面定义部分已经给出了我们桥接模式的目的以及实现思路了,下面让我们具体看看桥接模式是如何解决引言部分设计的不足。

抽象化部分的代码:


/// <summary>
 /// 抽象概念中的遥控器,扮演抽象化角色
 /// </summary>
 public class RemoteControl
 {
   // 字段
   private TV implementor;
   // 属性
   public TV Implementor
   {
     get { return implementor; }
     set { implementor = value; }
   }
   /// <summary>
   /// 开电视机,这里抽象类中不再提供实现了,而是调用实现类中的实现
   /// </summary>
   public virtual void On()
   {
     implementor.On();
   }
   /// <summary>
   /// 关电视机
   /// </summary>
   public virtual void Off()
   {
     implementor.Off();
   }
   /// <summary>
   /// 换频道
   /// </summary>
   public virtual void SetChannel()
   {
     implementor.tuneChannel();
   }
 }
 /// <summary>
 /// 具体遥控器
 /// </summary>
 public class ConcreteRemote : RemoteControl
 {
   public override void SetChannel()
   {
     Console.WriteLine("---------------------");
     base.SetChannel();
     Console.WriteLine("---------------------");
   }
 }

遥控器的实现方法部分代码,即实现化部分代码,此时我们用另外一个抽象类TV封装了遥控器功能的变化,具体实现交给具体型号电视机去完成:


/// <summary>
 /// 电视机,提供抽象方法
 /// </summary>
 public abstract class TV
 {
   public abstract void On();
   public abstract void Off();
   public abstract void tuneChannel();
 }
 /// <summary>
 /// 长虹牌电视机,重写基类的抽象方法
 /// 提供具体的实现
 /// </summary>
 public class ChangHong : TV
 {
   public override void On()
   {
     Console.WriteLine("长虹牌电视机已经打开了");
   }
   public override void Off()
   {
     Console.WriteLine("长虹牌电视机已经关掉了");
   }
   public override void tuneChannel()
   {
     Console.WriteLine("长虹牌电视机换频道");
   }
 }
 /// <summary>
 /// 三星牌电视机,重写基类的抽象方法
 /// </summary>
 public class Samsung : TV
 {
   public override void On()
   {
     Console.WriteLine("三星牌电视机已经打开了");
   }
   public override void Off()
   {
     Console.WriteLine("三星牌电视机已经关掉了");
   }
   public override void tuneChannel()
   {
     Console.WriteLine("三星牌电视机换频道");
   }
 }

采用桥接模式的客户端调用代码:


/// <summary>
 /// 以电视机遥控器的例子来演示桥接模式
 /// </summary>
 class Client
 {
   static void Main(string[] args)
   {
     // 创建一个遥控器
     RemoteControl remoteControl = new ConcreteRemote();
     // 长虹电视机
     remoteControl.Implementor = new ChangHong();
     remoteControl.On();
     remoteControl.SetChannel();
     remoteControl.Off();
     Console.WriteLine();
     // 三星牌电视机
     remoteControl.Implementor = new Samsung();
     remoteControl.On();
     remoteControl.SetChannel();
     remoteControl.Off();
     Console.Read();
   }
 }

上面桥接模式的实现中,遥控器的功能实现方法不在遥控器抽象类中去实现了,而是把实现部分用来另一个电视机类去封装它,然而遥控器中只包含电视机类的一个引用,同时这样的设计也非常符合现实生活中的情况(我认为的现实生活中遥控器的实现——遥控器中并不包含换台,打开电视机这样的功能的实现,遥控器只是包含了电视机上这些功能的引用,然后红外线去找到电视机上对应功能的的实现)。通过桥接模式,我们把抽象化和实现化部分分离开了,这样就可以很好应对这两方面的变化了。

另一个实例

来看一下经常用来被举例的汽车对象。
首先定义Abstraction。


public abstract class Car
 {
   public IEngine _engine;

public Car(IEngine engine)
   {
     _engine = engine;
   }

public virtual void Start()
   {
     _engine.Start();
   }

public virtual void Stop()
   {
     _engine.Stop();
   }
 }

接着实现不同的汽车类型。


public class Bus : Car
 {
   public Bus(IEngine engine)
     : base(engine)
   {
   }

public override void Start()
   {
     base.Start();
     Console.WriteLine("Bus Start");
   }

public override void Stop()
   {
     base.Stop();
     Console.WriteLine("Bus Stop");
   }
 }

public class Limousine : Car
 {
   public Limousine(IEngine engine)
     : base(engine)
   {
   }

public override void Start()
   {
     base.Start();
     Console.WriteLine("Limousine Start");
   }

public override void Stop()
   {
     base.Stop();
     Console.WriteLine("Limousine Stop");
   }
 }

再定义第二个变化维度,即发动机的接口。


public interface IEngine
  {
    void Start();
    void Stop();
  }

最后实现不同的发动机。


public class GasEngine : IEngine
 {
   public void Start()
   {
     Console.WriteLine("Gas Engine Start");
   }

public void Stop()
   {
     Console.WriteLine("Gas Engine Stop");
   }
 }

public class DieselEngine : IEngine
 {
   public void Start()
   {
     Console.WriteLine("Diesel Engine Start");
   }

public void Stop()
   {
     Console.WriteLine("Diesel Engine Stop");
   }
 }
标签:C#,桥接模式
0
投稿

猜你喜欢

  • android教程viewpager自动循环和手动循环

    2021-07-23 12:03:06
  • Apache Commons fileUpload文件上传多个示例分享

    2021-11-13 07:23:51
  • Java中的Gradle与Groovy的区别及存在的关系

    2023-05-13 17:28:46
  • SpringCloud Feign多参数传递及需要注意的问题

    2022-05-25 11:11:58
  • Android编程实现自动检测版本及自动升级的方法

    2023-06-07 16:24:23
  • Android仿QQ讨论组头像效果

    2021-08-13 14:08:32
  • java并发编程专题(三)----详解线程的同步

    2022-03-18 05:35:42
  • Java中二维数组的正确使用方法介绍

    2023-11-19 16:14:18
  • AjaxControlToolkit AjaxFileUpload 显示英文改成中文的解决方法

    2021-06-01 21:09:57
  • SpringBoot2.1.4中的错误处理机制

    2023-11-06 02:48:47
  • java结束进程的实例代码

    2023-11-10 14:18:38
  • 详解Java实现缓存(LRU,FIFO)

    2022-04-24 13:35:26
  • 一场由Java中Integer引发的踩坑实战

    2021-09-06 11:14:40
  • java volatile关键字的含义详细介绍

    2021-11-01 16:52:17
  • Java、JavaScript、Oracle、MySQL中实现的MD5加密算法分享

    2022-08-24 02:42:11
  • C#实现将网页保存成图片的网页拍照功能

    2021-06-22 14:36:01
  • Android 正则表达式验证手机号、姓名(包含少数民族)、身份证号

    2022-05-26 02:17:11
  • C#实现简单的聊天窗体

    2022-11-09 03:25:13
  • Android短信验证码(用的Mob短信验证)

    2022-12-16 15:22:41
  • Android实现长按back键退出应用程序的方法

    2023-03-26 21:49:43
  • asp之家 软件编程 m.aspxhome.com