在细说桥接模式之前先讲解一个例子,若干年前,手机操作系统不像现在这么统一,那个时候的手机应用开发就很让人头大,因为同样的软件要适配不同的机型,用结构图表示如下:
看看起来还很简单清晰的,那么问题来了,如果增加一个手机品牌S,那么它也有M品牌具备的相同功能,如果我还需要增加拍照功能、音乐播放功能等等,这就会导致类和类继承层次增长到不可控制的规模。
对象的继承关系是在编译时就定义好的,所以无法再运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换,这种依赖关系限制了灵活性并最终限制了复用性。这就涉及到了一个重要的设计原则:合成/聚合复用原则,即优先使用对象合成/聚合,而不是类继承。
合成/聚合都是关联的特殊种类,聚合表示一种弱的拥有关系,A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的声明周期一样。举例说:聚合就是一辆车和一个车队的关系,而合成则是一个引擎和一辆车的关系。
使用该原则时,优先使用对象的合成/聚合将有助于你保存每个类被封装,并被集中在单个任务上,这样和类继承层次会保持较小规模。
基于该原则就有了桥接模式,桥接模式将抽象部分与它的实现部分分离,使它们都可以独立的变化。而其中的实现指的是抽象类和它的派生类用来实现自己的对象。
Implementor类
package com.bridge;
/**
* @author Byp
*
*/
public abstract class Implementor {
public abstract void Operation();
}
ConcreteImplementorA类和ConcreteImplementorB类
package com.bridge;
/**
* @author Byp
*/
public class ConcreteImplementorA extends Implementor {
@Override
public void Operation() {
System.out.println("具体实现A的方法执行");
}
}
package com.bridge;
/**
* @author Byp
*/
public class ConcreteImplementorB extends Implementor {
@Override
public void Operation() {
System.out.println("具体实现B的方法执行");
}
}
Abstraction类
package com.bridge;
/**
* @author Byp
*/
public abstract class Abstraction {
protected Implementor implementor;
public void SetImplementor(Implementor implementor) {
this.implementor = implementor;
}
public abstract void Operation();
}
RefinedAbstraction类
package com.bridge;
/**
* @author Byp
*
*/
public class RefinedAbstraction extends Abstraction {
@Override
public void Operation() {
implementor.Operation();
}
}
Client测试类
package com.bridge;
/**
* @author Byp
*/
public class Test {
public static void main(String[] args) {
Abstraction abstraction = new RefinedAbstraction();
abstraction.SetImplementor(new ConcreteImplementorA());
abstraction.Operation();
abstraction.SetImplementor(new ConcreteImplementorB());
abstraction.Operation();
}
}
以上内容总结学习自程杰老师的大话设计模式