一、定义
桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化。
主要解决:在多维可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。
如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
注意事项:对于两个独立变化的维度,使用桥接模式再适合不过了。
二、结构
三、实现
一般写法
namespace DesignPatterns.Bridge { class Program { static void Main(string[] args) { CarOnSpeedWay carOnSpeedWay = new CarOnSpeedWay(); BusOnSpeedWay busOnSpeedWay = new BusOnSpeedWay(); CarOnStreet carOnStreet = new CarOnStreet(); BusOnStreet busOnStreet = new BusOnStreet(); carOnSpeedWay.Run(); busOnSpeedWay.Run(); carOnStreet.Run(); busOnStreet.Run(); Console.WriteLine("==== 这是分割线 ====="); } } public class Road { public virtual void Run() { Console.WriteLine("在路上跑"); } } public class SpeedWay : Road { public override void Run() { Console.WriteLine("在高速上跑"); } } public class Street : Road { public override void Run() { Console.WriteLine("在大街上跑"); } } public class CarOnSpeedWay : SpeedWay { public override void Run() { Console.WriteLine("汽车在高速上跑"); } } public class BusOnSpeedWay : SpeedWay { public override void Run() { Console.WriteLine("大巴在高速上跑"); } } public class CarOnStreet : Street { public override void Run() { Console.WriteLine("汽车在大街上跑"); } } public class BusOnStreet : Street { public override void Run() { Console.WriteLine("大巴在大街上跑"); } } }
显示结果
可以看到,如果又增加了道路类型(乡村道路)、车型(电动车、摩托车),那么就变的非常复杂庞大,扩展困难,又造成类爆炸。
使用桥接模式来避免这个问题,代码如下
namespace DesignPatterns.Bridge { class Program { static void Main(string[] args) { Console.WriteLine("==== 这是分割线 ====="); AbstractRoad road1 = new SpeedWay(new Car()); road1.Run(); Console.WriteLine(".............."); AbstractRoad road2 = new Street(new Bus()); road2.Run();
Console.Read(); } } public abstract class AbstractCar { public abstract void Run(); } public class Car : AbstractCar { public override void Run() { Console.WriteLine("汽车在"); } } public class Bus : AbstractCar { public override void Run() { Console.WriteLine("大巴在"); } } public abstract class AbstractRoad { protected AbstractCar car; public AbstractCar Car { set { car = value; } } public abstract void Run(); } public class SpeedWay : AbstractRoad { public SpeedWay(AbstractCar car) { this.car = car; } public override void Run() { car.Run(); Console.WriteLine("高速上跑"); } } public class Street : AbstractRoad { public Street(AbstractCar car) { this.car = car; } public override void Run() { car.Run(); Console.WriteLine("大街上跑"); } } }
四、使用场景
在以下情况下应当使用桥接模式:
- 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系。
- 设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的。
- 需要跨越多个平台的图形和窗口系统上。
- 一个类存在两个独立变化的维度,且两个维度都需要进行扩展。
实际遇到过的应用:
非常典型的例子 -- JDBC驱动程序
人力资源系统中的奖金计算模块:
奖金分类:个人奖金,团体奖金,项目奖金,激励奖金
部门分类:人事部,销售部,研发部
OA系统中的消息处理:
业务类型:普通消息,加急消息,特急消息
发送消息方式:系统内消息,手机短信,邮件
五、优缺点
优点:
把抽象接口与其实现解耦。
抽象和实现可以独立扩展,不会影响到对方。
实现细节对客户透明,对用于隐藏了具体实现细节。
缺点:
增加了系统的复杂度
参考文章:
http://www.runoob.com/design-pattern/bridge-pattern.html
http://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html
http://www.cnblogs.com/JsonShare/p/7233342.html
http://www.cnblogs.com/zhili/p/BridgePattern.html
欢迎阅读本系列文章:Head First设计模式之目录