桥接模式
当一个抽象可能有多个实现时,通常用继承来进行协调。抽象类定义对该抽象的接口,而具体的子类则用不同的方式加以实现。继承机制将抽象部分与它的实现部分固定在一起,使得难以对抽象部分和实现部分独立地进行修改、扩充和重用。
如果一个抽象类或接口有多个具体实现子类,而这些子类之中有内容或概念上重叠,需要我们把抽象的共同部分各自独立开来:即原来是准备放在一个接口里,现在需要设计两个接口——抽象接口和行为接口。然后再分别针对各自的具体子类定义抽象接口和行为接口的方法和调用关系。
简单来说,就是把一个对象的描述和行为分来来设计。这样,当行为发生变化时,对已有的对象不需要再次修改。当对象的描述变化时,对行为也没有任何的影响。
定义
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
优点
- 抽象与实现分离,扩展能力强
- 符合开闭原则
- 符合合成复用原则
- 其实现细节对客户透明
缺点
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
模式结构
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
在桥接模式中,两个类Abstraction和Implementor分别定义了抽象与行为类型的接口,通过调用两接口的子类实现抽象与行为的动态组合。
应用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
- 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
- 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
示例
我们在描述动物的时候,可以这样描述:“这是一只老虎,它会跑。”如果使用一个父类的话,我们需要实现老虎,还需要实现他的跑的方法,如果这时候一只鸟也实现了老虎的父类,但是鸟需要飞,则需要在父类中添加飞的接口,但是老虎不会飞,实现这个接口没有意义。如果老虎和鸟各自实现自己的方法,则父类只是定义了一个构造方法,存在的意义也不大。
这时,只需要将父类的定义方式和动作的实现方式分离开来,便可以使用一个父类实现老虎和鸟,或者鱼的对象。
动作
package com.designpattern.bridge.operations;
public interface Operation {
void move();
}
飞
package com.designpattern.bridge.operations;
public class Fly implements Operation{
@Override
public void move() {
System.out.println("Flying......");
}
}
跑
package com.designpattern.bridge.