桥接模式
桥接模式是一种比较常见的结构型设计模式,如果系统中的某个类存在两个独立变化的维度,通过桥接模式可以将这两个维度分离出来,使两者可以独立扩展。
桥接模式是一个非常实用的设计模式,它体现了很多面向对象设计原则的思想,单一职责原则、接口隔离原则、合成复用原则、开闭原则、依赖倒转原则、里氏替换原则等。
定义
桥接模式将抽象部分与它的实现部分解耦,使两者都能够独立变化。它用抽象关联取代了传统的多层继承,将类之间的静态继承关系转换为动态的对象组合关系,使系统更加灵活,易于扩展,有效控制了系统中类的个数。
结构
- Abstraction(抽象类): 用于定义抽象类的接口,通常是类而不是接口,它定义了一个Implementor成员变量,与Implementor的实现类关联,用来表示分离出去的另一个维度。
- RefinedAbstraction(扩充抽象类):Abstraction的实现类,实现了父类维度的功能,同时可以调用Implementor维度的功能。
- Implementor(实现类接口): 分离出去的另一个维度,可以被Abstraction调用。
- ConcreteImplementor(具体实现类): 实现Implementor的抽象功能,运行时为Abstraction提供具体的业务方法。
举例
在使用桥接模式的时候,要准确的识别出一个类所具有的两个或者多个独立变化的维度,将它们设计成独立的继承等级结构,提供抽象层并建立抽象耦合。
参考桥接模式的定义可以知道,这种设计模式的实用性非常强,下面举个例子,通过代码来模拟一个小区的建设。通常小区都有楼房、花园这里两个核心,可以用下面代码表示。
package abstraction;
public abstract class ResidentionPlan {
private GardenPlan gradenPlan;
public GardenPlan getGradenPlan() {
return gradenPlan;
}
public void setGradenPlan(GardenPlan gradenPlan) {
this.gradenPlan = gradenPlan;
}
public abstract void executePlan();
}
package abstraction;
import java.util.Objects;
public class VillaResidentionPlan extends ResidentionPlan {
@Override
public void executePlan() {
System.out.println("建设别墅房屋");
if (!Objects.isNull(this.getGradenPlan())) {
this.getGradenPlan().executePlan();
}
}
}
package abstraction;
public interface GardenPlan {
public void executePlan();
}
package abstraction;
public class ChildPlayGroundPlan implements GardenPlan {
@Override
public void executePlan() {
System.out.println("建设儿童游乐园");
}
}
package abstraction;
public class Test {
public static void main(String args[]) {
ResidentionPlan residentionPlan = new VillaResidentionPlan();
residentionPlan.setGradenPlan(new ChildPlayGroundPlan());
residentionPlan.executePlan();
}
}
如果要更换小区设计风格或者花园设计,那么只创建一个新的类,并且对Client中的类进行替换就可以了,而这一步完全可以通过配置文件等进行实现,再无需其他修改。
桥接模式优点
- 按照维度分离了抽象类及其实现部分,桥接模式使用"对象间的关联关系"解耦了抽象和实现之间的固有绑定关系,使的抽象和实现可以沿着各自的维度进行变化。
- 解决了多层继承情况下类数量过多且耦合性太强、扩展性低的问题。
- 提高了系统的扩展性,系统按照各自的维度进行扩展,不会对其他维度产生影响。
适用场景
- 一个类存在两个或者多个变化的维度,并且这两个维度都要独立地进行扩展。
- 系统业务比较复杂,扩展需求比较多,对单个维度的扩展容易对其他方面产生影响。