一、定义
桥接模式(bridge pattern),将抽象部分与它的实现部分分离,是它们都可以独立的变化。
二、使用场景
1、如果一个系统需要在构件的抽象化角色和实现化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
2、抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
4、虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
三、角色分析
抽象化角色(Abstraction):抽象化给出的定义,并保存一个对实现化对象的引用
扩充抽象化角色(RefinedAbstraction)【修正抽象化(Refined Abstraction)角色】:扩展抽象化角色,改变和修正父类对抽象化的定义
实现化角色(Implementor):实现化角色的接口,但不给出具体的实现
具体实现化角色(ConcreteImplementor):具体实现
四、代码示例
故事背景:城市A和城市B是分隔两岸的两座城市,他们通过一座拥有悠久历史的桥连接起来。城市A人文气息浓厚,商店林立,人来人往,熙熙攘攘。城市B工业气息浓厚,各种机器和手工作坊相辉映,在重复的工序中输出产品。城市A和城市B交互的模式,一般是城市A下订单,城市B完成订单。
这里对于订单来说有两个维度,一个是种类:蛋糕或糖果,一种是制作方式:手工或机器制作。如果没有使用桥接模式的话,就有四种组合方式,就是四个类,但是如果增加了种类或者制作方式的话,需要继续计算组合方式,类增长的速度不是我们想要的。当使用了桥接模式之后,添加种类或制作方式只需要添加继承抽象化对象或者实现化对象增加需要变化的维度的对象即可。
抽象化角色(OrderAbstraction.java):
// 订单
public abstract class OrderAbstraction {
protected FactoryImplementor factoryImplementor;
public OrderAbstraction(FactoryImplementor factoryImplementor) {
this.factoryImplementor = factoryImplementor;
}
public abstract void provide();
}
扩充抽象化角色(CakeOrderRefinedAbstraction.java):
// 蛋糕订单
public class CakeOrderRefinedAbstraction extends OrderAbstraction {
private int count;
private String orderName = "蛋糕";
public CakeOrderRefinedAbstraction(int count, FactoryImplementor factoryImplementor) {
super(factoryImplementor);
this.count = count;
}
@Override
public void provide() {
factoryImplementor.provide(count, orderName);
}
}
// 糖果订单
public class CandyOrderRefinedAbstraction extends OrderAbstraction {
private int count;
private String orderName = "糖果";
public CandyOrderRefinedAbstraction(int count, FactoryImplementor factoryImplementor) {
super(factoryImplementor);
this.count = count;
}
@Override
public void provide() {
factoryImplementor.provide(count, orderName);
}
}
实现化角色(FactoryImplementor.java):
// 工厂
public interface FactoryImplementor {
public void provide(int count, String orderName);
}
具体实现化角色(HandworkFactoryConcreteImplementor.java、MachineFactoryConcreteImplementor.java):
// 手工作坊
public class HandworkFactoryConcreteImplementor implements FactoryImplementor {
public void provide(int count, String orderName) {
float time = (float)(count * 1);
System.out.println("手工使用了" + time + "小时,完成了" + count + "份" + orderName);
}
}
// 工厂机器
public class MachineFactoryConcreteImplementor implements FactoryImplementor {
public void provide(int count, String orderName) {
float time = (float)(count * 0.5);
System.out.println("机器使用了" + time + "小时,完成了" + count + "份" + orderName);
}
}
测试类(BridgePatternTest.java):
public class BridgePatternTest {
public static void main(String[] args) {
// 手工蛋糕订单
OrderAbstraction handworkCake =
new CakeOrderRefinedAbstraction(10,
new HandworkFactoryConcreteImplementor());
// 机器蛋糕订单
OrderAbstraction machineCake =
new CakeOrderRefinedAbstraction(10,
new MachineFactoryConcreteImplementor());
// 手工糖果订单
OrderAbstraction handworkCandy =
new CandyOrderRefinedAbstraction(10,
new HandworkFactoryConcreteImplementor());
// 机器糖果订单
OrderAbstraction machineCandy =
new CandyOrderRefinedAbstraction(10,
new MachineFactoryConcreteImplementor());
handworkCake.provide();
machineCake.provide();
handworkCandy.provide();
machineCandy.provide();
}
}
测试结果:
五、优缺点
优点
1、抽象和实现分离
2、多维度变化
缺点
1、增加系统的设计和理解难度
总结
当在系统设计初期,发现抽象和实现存在各自的变化或某个类由两个不相关的维度描述时,可以考虑桥接模式。