定义
将实现与抽象分开,使他们都可以独立地变化。或者说是将隶属关系的两层分开为两个维度,两个维度分别抽象,两个抽象通过“桥”进行连接,这个“桥”可以是其中一个抽象,两个抽象的具体实现可以自由扩展,实现了对修改关闭对扩展开放
- UML
案例&解析
假如此时需要维护手机机型对应手机品牌的关系,具体的关系如下图中(1)
- 上图(1)得到一个抽象继承的关系网,并且手机类型和手机品牌呈现隶属关心,品牌隶属了手机类型,一旦想增加某款机型,需要增加已知所有品牌手机,反过来要增加一中新的品牌“魅族”需要在各个机型中增加该品牌,这样属于维护了一个静态的关系,会导致很多的类还丧失了灵活性(比如XiaoMi没有Slide机型只有Clamshell机型,这些关系都是编码组织时都已经定下来的)
- 而(2)中通过桥接模式无论新增机型还是新增品牌,都只需要添加对应的机型或品牌即可,并且可以在client对机型和品牌进行自由组合
- 代码如下
// ------机型-----
public abstract class Phone {
protected String type;
protected Brand brand;
public void call() {
System.out.println(brand.getName() + type + ":打电话");
}
public void message() {
System.out.println(brand.getName() + type + ":发短信");
}
}
public class SlidePhone extends Phone {
public SlidePhone(Brand brand) {
super.brand = brand;
super.type = "滑盖";
}
}
public class ClamshellPhone extends Phone {
public ClamshellPhone(Brand brand) {
super.brand = brand;
super.type = "翻盖";
}
}
// ------品牌-----
public abstract class Brand {
private String name;
public Brand(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Vivo extends Brand {
public Vivo() {
super("Vivo");
}
}
public class XiaoMi extends Brand {
public XiaoMi() {
super("xiaomi");
}
}
public class Huawei extends Brand {
public Huawei() {
super("huawei");
}
}
// ------client-----
public class Client {
public static void main(String[] args) {
Phone phone1 = new SlidePhone(new Vivo());
phone1.call();// Vivo滑盖:打电话
Phone phone2 = new SlidePhone(new XiaoMi());
phone2.call();// xiaomi滑盖:打电话
Phone phone3 = new SlidePhone(new Huawei());
phone3.message();// huawei滑盖:发短信
Phone phone4 = new ClamshellPhone(new XiaoMi());
phone4.message();// xiaomi翻盖:发短信
}
}
桥接模式的用途&优缺点
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展
- 抽象化角色(上面的phone比如要加一个上网的功能,只需要在抽象Phone上加一个surfIntenet方法即可,这里可以理解为对抽象的修改)和具体化角色(比如对具体类型和品牌的扩展修改,这里理解为对具体的修改)需要独立变化
- 不许忘使用继承或因多层次继承导致系统类的个数继续增加的系统,桥接模式尤为适合
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系