桥接模式,也称为桥梁模式,英文是 Bridge Pattern。有两种解释:第一种,是经典的GOF《设计模式》中描述到,“将抽象和实现解耦,让它们可以独立变化”。第二种,是其他相关书籍中描述的,”一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展“。
注意:
对于第一种 GOF 的理解方式,弄懂定义中“抽象”和“实现”两个概念,是理解它的关键。定义中的“抽象”,指的并非“抽象类”或“接口”,而是被抽象出来的一套“类库”,它只包含骨架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。而定义中的“实现”,也并非“接口的实现类”,而是一套独立的“类库”。“抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。”抽象“和”实现”实质上对应的是两个独立变化的维度。
适用范围
1,一个类存在两个或者多个独立变化的维度,且者两个或多个维度都需要进行扩展,就可以使用桥接模式;
2,任何多维度变化类或者说多个树状类之间的耦合都可以使用桥接模式来解耦;
相信大家喝过奶茶,可以简单把奶茶分为大杯少糖,小杯少糖,大杯多糖,小杯多糖;可以发现一杯奶茶有两个维度,一是:大杯,小杯;二是:少糖,多糖;下面我们用代码实现;
定义奶茶类(“抽象”)
public abstract class MilkyTea {
protected MilkyTeaAdditives additives;
public MilkyTea(MilkyTeaAdditives additives) {
this.additives = additives;
}
//奶茶具体是什么样的,由子类实现
public abstract void makeMilkyTea();
}
MilkyTea通过组合引用了MilkyTeaAdditives;下面实现第一个维度:大杯小杯维度;
public class LargeMikyTea extends MilkyTea {
public LargeMikyTea(MilkyTeaAdditives additives) {
super(additives);
}
@Override
public void makeMilkyTea() {
System.out.println("大杯"+ additives.addSomething() + "奶茶" );
}
}
public class SmallMilkyTea extends MilkyTea {
public SmallMilkyTea(MilkyTeaAdditives additives) {
super(additives);
}
@Override
public void makeMilkyTea() {
System.out.println("小杯"+ additives.addSomething() + "奶茶");
}
}
对于加料糖,我们定义一个接口(“实现”)
public interface MilkyTeaAdditives {
String addSomething();
}
另一个维度:少糖和多糖,代码实现如下:
public class LargeSugar implements MilkyTeaAdditives {
@Override
public String addSomething() {
return "多糖";
}
}
public class SmallSugar implements MilkyTeaAdditives {
@Override
public String addSomething() {
return "少糖";
}
}
成品
public class Client {
public static void main(String[] args) {
LargeSugar largeSugar = new LargeSugar();
SmallSugar smallSugar = new SmallSugar();
//大杯多糖
LargeMikyTea largeMikyTea = new LargeMikyTea(largeSugar);
largeMikyTea.makeMilkyTea();
//大杯少糖
LargeMikyTea largeMikyTea1 = new LargeMikyTea(smallSugar);
largeMikyTea1.makeMilkyTea();
//小杯多糖
SmallMilkyTea smallMilkyTea = new SmallMilkyTea(largeSugar);
smallMilkyTea.makeMilkyTea();
//小杯少糖
SmallMilkyTea smallMilkyTea1 = new SmallMilkyTea(smallSugar);
smallMilkyTea1.makeMilkyTea();
}
}
随着市场变化,为了满足更多的客户,现在推出中杯;
public class MiddleMilkyTea extends MilkyTea {
public MiddleMilkyTea(MilkyTeaAdditives additives) {
super(additives);
}
@Override
public void makeMilkyTea() {
System.out.println("中杯"+additives.addSomething() + "奶茶!");
}
}
对应的成品增加
public class Client {
public static void main(String[] args) {
LargeSugar largeSugar = new LargeSugar();
SmallSugar smallSugar = new SmallSugar();
//..................................
//中杯多糖
MiddleMilkyTea middleMilkyTea = new MiddleMilkyTea(largeSugar);
middleMilkyTea.makeMilkyTea();
//中杯少糖
MiddleMilkyTea middleMilkyTea1 = new MiddleMilkyTea(smallSugar);
middleMilkyTea1.makeMilkyTea();
}
}
但是仅仅增加中杯是不够的,很多客户需要添加其他的配料,比如珍珠,西米,红豆等等,具体只需要实现MilkyTeaAdditives接口,增加其他配料就好,具体就不用代码实现了;相信大家都能实现;
总结:两个维度没什么交集,唯一的联系就是MilkTea中通过组合保持了对MilkTeaAdditives的引用,通过组合形成了两者之间的纽带,这就是桥接模式;