背景
在现实生活中,一个物体往往具有多个方面的属性。如果我们将人进行归类。我们可以按性别分类,也可以按肤色分类,也可以按所处的地区分类,还可以按自己的母语分类。
在代码中我们如何让表示这个人呢。如果以继承的方式表示,就会出现很多子类,这样扩展就会很麻烦。
我们可以使用桥接模式来解决这些问题。
什么是桥接模式
“Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦,使得两者可以独立地变化。)
”
桥接模式使用组合模式来代替继承关系,这样可以降低抽象与实现之间的耦合度。
桥接模式主要组成结构:
“”
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
桥接模式
代码实现
Implementor
interface Implementor {
void operationImpl();
}
ConcreteImplementorA
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("具体实现化(Concrete Implementor)角色被访问");
}
}
Abstraction
public abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
RefinedAbstraction
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
System.out.println("扩展抽象化(Refined Abstraction)角色被访问" );
implementor.operationImpl();
}
}
测试代码
public class BridgeTest {
public static void main(String[] args){
Implementor implementorA = new ConcreteImplementorA();
RefinedAbstraction refinedAbstraction = new RefinedAbstraction(implementorA);
refinedAbstraction.operation();
}
}
测试结果:
扩展抽象化(Refined Abstraction)角色被访问
具体实现化(Concrete Implementor)角色被访问
关于桥接模式的思考
桥接模式的一个常见使用场景就是替换继承。我们知道,继承拥有很多优点,比如,抽象、封装、多态等,父类封装共性,子类实现特性。继承可以很好的实现代码复用(封装)的功能,但这也是继承的一大缺点。
因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为优先使用组合/聚合,而不是继承。
使用桥梁模式时主要考虑如何拆分抽象和实现,并不是一涉及继承就要考虑使用该模式,那还要继承干什么呢?桥梁模式的意图还是对变化的封装,尽量把可能变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。因此我们在进行系统设计时,发现类的继承有N层时,可以考虑使用桥梁模式。