桥接模式是结构型设计模式,桥接模式本身应对的是由于实际的需要,使用不同纬度的条件和方法,桥接模式可以将两个类型分离出来,让两者之间都可以独立的拓展,让每一个类都更加符合单一职责。桥接模式与多层继承方案有些不太相同,它让两个独立变化的设计成为两个独立的继承等级的类,并且在抽象简历一个抽象关系,该关系类似一条连接两个继承结构的桥。
桥接模式用了一种巧妙的方式处理多层继承存在的问题,用抽象关联取代传统的多层继承关系,将类与静态继承关系转换成动态的对象组合关系,是得系统更加灵活,易于拓展,同时有效的控制系统类中类的个数。
什么是桥接模式
桥接模式:桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(interface)模式。 ——节选自百度百科
桥接模式通过将继承改为组合的方式来解决这个问题。具体来说,就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象,从而使得一个类不必拥有所有的状态和行为。桥接模式主要应对的是由于实际的需要,某个类具有两个或者两个以上的维度变化,如果只是用继承将无法实现这种需要,或者使得设计变得相当臃肿。
桥接模式优缺点
桥接模式中的抽象部分持有具体实现部分的接口,最终目的是通过调用具体实现部分的接口中的方法,进一步完成一定的功能,这跟直接使用接口没有什么差异,只是表现形式略有不同而已。其次,使用接口的客户程序也可以持有相应的接口对象,这样从形式上就一样了。也就是说,从某个角度来讲,桥接模式是面向抽象编程
这个设计原则的扩展。
正是通过具体实现的接口,把抽象部分和具体的实现分离开来,抽象部分相当于是使用实现部分接口的客户程序,这样抽象部分和实现部分就松散耦合了,从而可以实现相互独立的变化。这样一来,几乎可以把所有面向抽象编写的程序,都视作是桥接模式的体现,至少算是简化的桥接模式,就算是广义的桥接吧。
优点
缺点
对高内聚的类使用桥接模式可能会让代码更加复杂化
示例
桥接模式的主要角色如下:
类图如下所示:
代码示例:
// 实现接口角色 interface Implementor { doSomething() : void; doAnything() : void; } // 具体实现角色 class ConcreteImplementor1 implements Implementor { public doSomething() : void { } public doAnything() : void { } } class ConcreteImplementor2 implements Implementor { public doSomething() : void { } public doAnything() : void { } } // 抽象类 abstract class Abstraction { private imp : Implementor; constructor(imp : Implementor) { this.imp = imp; } // 自身的行为和属性 public request() : void { this.imp.doSomething(); } } // 具体抽象化角色 class RefinedAbstraction extends Abstraction { constructor(imp : Implementor) { super(imp); } public request() : void { // 自己写一些处理业务 super.request(); } } // 调用 // 定义一个实现化角色 const imp : Implementor = new ConcreteImplementor1(); // 定义一个抽象化角色 const abs : Abstraction = new RefinedAbstraction(imp); // 执行上下文 abs.request();
总结
如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间简历静态的继承关系,通过桥接模式可以使他们在抽象层建立关系。
抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。