桥接模式(Bridge)
定义
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。
类图
描述
Abstraction:定义抽象部分的接口,通常在这个接口里面要维护一个实现部分的对象引用;在抽象部分的方法里面需要调用实现部分的方法,这个抽象部分的方法里面通常都是跟具体的业务相关的方法;
RefinedAbstraction:扩展抽象部分的接口,通常在这些方法里面定义跟实际业务相关的方法,这些方法通常会使用Abstraction中定义的方法,也可能需要调用实现部分的方法来完成;
Implementor:定义实现部分的接口,这个接口不用和Abstraction里面的方法一致,通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作;
ConcreteImplementor:实现Implementor接口。
应用场景
手机品牌有MEIZU、IPhone等品牌,每种手机都可以安装音乐、游戏等app,但是MEIZU手机的操作系统是Flyme OS基于Android,IPhone的操作系统是IOS,所以同一款音乐或游戏app都要有Android和IOS两种版本。
按手机品牌划分的类图如下:
按app功能划分的类图如下:
如果现在要增加一种WP操作系统的手机,那么就需要在MobilePhone下增加一个子类,同时给这个子类增加音乐和游戏的app子类;如果再增加一个导航功能的app,那么就需要在每种手机下增加一个导航app子类;如果再增加其他手机或其他功能的app,那么上述类图将会变得无比庞大。这时就需要对类图作一些改进。
从上述类图可以看到,手机上可以安装音乐、游戏等app,也可以不安装,不管安不安装这些app,都不会影响手机的使用,由此可见手机和app之间的关系是一种聚合关系。于是,可以把上面的类图改为如下:
这样就把手机和app分离开了,也就意味着如果要增加手机种类,只需在MobilePhone下增加一个子类;如果要增加app种类,只需在MobilePhoneApp下增加一个子类;不管是增加手机或是app的种类都不会影响其他类。
组合/聚合复用原则,尽量使用组合/聚合,而不要使用类继承。
public abstract class MobilePhoneApp { public abstract void Run(); } public class Music : MobilePhoneApp { public override void Run() { Console.WriteLine("运行手机音乐."); } } public class Game : MobilePhoneApp { public override void Run() { Console.WriteLine("运行手机游戏."); } } public abstract class MobilePhone { protected MobilePhoneApp app; public MobilePhone(MobilePhoneApp app) { this.app = app; } public abstract void Run(); } public class MEIZU : MobilePhone { public MEIZU(MobilePhoneApp app) : base(app) { } public override void Run() { this.app.Run(); } } public class IPhone : MobilePhone { public IPhone(MobilePhoneApp app) : base(app) { } public override void Run() { this.app.Run(); } }