第十章:桥接模式
一、问题引入
现奶茶店有上述多种奶茶(实际情况可能更多),如果需要我们设计一个点奶茶的程序,传统的方案如上图所示,采用继承的方式,让每一种奶茶都对应一个子类。问题也显然一见,这样做会导致类爆炸。
我们看到,一杯奶茶主要有两个特点,即尺寸和所加的配料,这两个特点相乘就导致了很多的类,所以为了减少类的数量,我们将这两个特点拆成两种类。将奶茶的尺寸作为桥接类(两个特点最后当然要组合起来才能构成一杯具体的奶茶,所以两个特点类必有一个桥接类)。
二、桥接模式
类图如下:
MilkyTea 抽象类
public abstract class MilkyTea {
protected Ingredient ingredient;
public MilkyTea(Ingredient ingredient) {
this.ingredient = ingredient;
}
public abstract void addTea();
public abstract void addWater();
public abstract void addMilk();
public abstract void addSuger();
public abstract void getInfo();
public void makeMilkyTea() {
addTea();
addWater();
addMilk();
addSuger();
ingredient.addIngredient();
getInfo();
}
}
MilkyTea 子类
public class BigMilkyTea extends MilkyTea {
public BigMilkyTea(Ingredient ingredient) {
super(ingredient);
}
@Override
public void addTea() {
System.out.println("加大量茶叶");
}
@Override
public void addWater() {
System.out.println("加大量水");
}
@Override
public void addMilk() {
System.out.println("加大量牛奶");
}
@Override
public void addSuger() {
System.out.println("加大量糖");
}
@Override
public void getInfo() {
System.out.println("大杯"+ ingredient.getInfo() +"奶茶");
}
}
public class MediumMilkyTea extends MilkyTea {
public MediumMilkyTea(Ingredient ingredient) {
super(ingredient);
}
@Override
public void addTea() {
System.out.println("加一些茶叶");
}
@Override
public void addWater() {
System.out.println("加一些水");
}
@Override
public void addMilk() {
System.out.println("加一些牛奶");
}
@Override
public void addSuger() {
System.out.println("加一些糖");
}
@Override
public void getInfo() {
System.out.println("中杯" + ingredient.getInfo() + "奶茶");
}
}
public class SmallMilkyTea extends MilkyTea {
public SmallMilkyTea(Ingredient ingredient) {
super(ingredient);
}
@Override
public void addTea() {
System.out.println("加少许茶叶");
}
@Override
public void addWater() {
System.out.println("加少许水");
}
@Override
public void addMilk() {
System.out.println("加少许牛奶");
}
@Override
public void addSuger() {
System.out.println("加少许糖");
}
@Override
public void getInfo() {
System.out.println("小杯" + ingredient.getInfo() + "奶茶");
}
}
Ingredient 接口
public interface Ingredient {
void addIngredient();
String getInfo();
}
Ingredient 接口实现类
public class CoconutIngredient implements Ingredient {
@Override
public void addIngredient() {
System.out.println("加一些椰果");
}
@Override
public String getInfo() {
return "椰果";
}
}
public class PearlIngredient implements Ingredient {
@Override
public void addIngredient() {
System.out.println("加一些珍珠");
}
@Override
public String getInfo() {
return "珍珠";
}
}
测试类
public class BridgeTest {
public static void main(String[] args) {
MediumMilkyTea mediumMilkyTea = new MediumMilkyTea(new CoconutIngredient());
mediumMilkyTea.makeMilkyTea();
System.out.println("====================");
BigMilkyTea bigMilkyTea = new BigMilkyTea(new PearlIngredient());
bigMilkyTea.makeMilkyTea();
}
}
这样我们仅使用了 7 个类就解决了问题,而且既符合单一职责原则,又符合合成复用原则
三、桥接总结
1)桥接模式需要正确识别出系统中两个独立变化的维度,所以使用范围有一定局限性
2)桥接模式将事物的两方面的特征分离,提高了灵活性,减少了类的个数
|