1 定义
桥接模式(Bridge Pattern),又叫柄体(Handle and Body)模式或接口(Interface)模式,属于结构型设计模式,它主要用于当对象存在多个维度特征时将维度分离出来,让抽象部分和实现部分分离,使每个维度可以独立扩展。它是继承关系的一个替代方案,且在特定场景中比使用继承生成子类更具有灵活性和可扩展性。例如现实场景中,我们要去吃一碗面,菜单上标着有牛肉面、鸡肉面,然后可以根据自己喜爱搭配辅食有香肠和鸡蛋。想象一下,如果使用继承来实现的话,会存在4种继承于面条的具体口味的面条,有:加香肠的牛肉面、加鸡蛋的牛肉面、加香肠的鸡肉面和加鸡蛋的鸡肉面,然而如果后面店家每增加一种肉面或辅食,具体口味的面条的子类都要乘方地增加,这显示不实际。所以桥接模式就是为解决此类场景而诞生。
2 实现
桥接模式一般包含4个角色,分别是:
- 抽象(Abstraction),就是抽象的定义,内部包含一个Implementor对象的引用。例如上述定义举例的面条的统称。
- 精确抽象(RefinedAbstraction),就是拓展Abstraction,更精确的抽象。例如上述定义举例的牛肉面和鸡肉面。
- 抽象实施(Implementor),就是次维度的抽象定义,提供当前维度基本接口定义。例如上述定义举例的辅食。
- 具体实施(ConcreteImplementor),就是继承于Implementor的具体实现。例如上述定义举例的香肠和鸡蛋。
抽象类,它是面条的统称,内部包含一个Ingredient对象,它是Implementor对象:
public abstract class Noodle {
protected Ingredient mIngredient;
public void setIngredient(Ingredient ingredient) {
mIngredient = ingredient;
}
public abstract void show();
}
精确抽象类,它是具体的面条:
public class BeefNoodle extends Noodle {
@Override
public void show() {
if (mIngredient != null) {
System.out.println("加了" + mIngredient.getName() + "的牛肉面");
}
}
}
public class ChickenNoodle extends Noodle {
@Override
public void show() {
if (mIngredient != null) {
System.out.println("加了" + mIngredient.getName() + "的鸡肉面");
}
}
}
抽象实施类,它也是抽象类或接口,表示一个次维度,这里代表着辅食:
public abstract class Ingredient {
public abstract String getName();
}
具体实施类,它继承于抽象实施Ingredient,代表具体的一种辅食香肠或者鸡蛋:
public class SausageIngredient extends Ingredient {
@Override
public String getName() { return "香肠"; }
}
public class EggIngredient extends Ingredient {
@Override
public String getName() { return "鸡蛋"; }
}
客户端:
Noodle beefNoodle = new BeefNoodle();
beefNoodle.setIngredient(new EggIngredient());
beefNoodle.show();
beefNoodle.setIngredient(new SausageIngredient());
beefNoodle.show();
Noodle chickenNoodle = new ChickenNoodle();
chickenNoodle.setIngredient(new EggIngredient());
chickenNoodle.show();
chickenNoodle.setIngredient(new SausageIngredient());
chickenNoodle.show();
输出结果:
加了鸡蛋的牛肉面
加了香肠的牛肉面
加了鸡蛋的鸡肉面
加了香肠的鸡肉面
3 总结
桥接模式在遇到多维度特征的对象时,因为每一种维度分类都有可能变化,那么就把这种多维度分离出来让它们独立变化,然后在使用上再将它们进行连接起来,这样能有效减少它们之间的耦合。相比使用继承会更加灵活,因为继承是强耦合关系,子类与父类有非常紧密的依赖关系,父类的任何变化 都会导致子类发生变化。但在设计上要求正确识别出独立变化的维度和由于聚合关联关系建立在抽象层也增加了系统的理解和设计难度。