是设计模式,我们有救了!!!(六、桥接模式)

桥接模式--解耦抽象与实现的设计艺术

其核心思想是将抽象部分与实现部分分离 ,使它们可以独立变化而不互相影响。这种模式通过组合关系替代继承关系 ,有效解决了多维度变化导致的类爆炸问题,提高了系统的灵活性和可扩展性。

让我们来举一个做咖啡为基础的场景说明一些问题: 假设我们的咖啡只有两个维度: 制作咖啡本身的流程makeCoffee,和添加一些不属于咖啡本身的东西(比如、加糖,加奶、加柠檬之类的)。那么现在我们的抽象就是这样的:

csharp 复制代码
public abstract class BaseCoffee {
    public abstract String add();
    public abstract void makeCoffee();
}

至于具体的实现,我们可以放在子类当中去做: 因此我们可能会想去制作加糖的美式咖啡

scala 复制代码
public class AmericanCoffeeSugar extends BaseCoffee{
    @Override
    public String add() {
        return "加糖";
    }

    @Override
    public void makeCoffee() {
        System.out.println("美式咖啡"+add());
    }
}

也可能是加奶的意式咖啡

scala 复制代码
public class ItalianCoffeeMilk extends BaseCoffee {
    @Override
    public String add() {
        return "加奶";
    }

    @Override
    public void makeCoffee() {
        System.out.println("意式咖啡" + add());
    }
}

当然,我们现在不考虑好不好喝的问题,为了尽可能的满足客户端的需要,我们必须要提供每种制作工艺(makeCoffee)和额外添加(add)的组合。 现在再回过头来看问题:

  • 抽象部分与实现部分分离?

  • 当然没有分离,我们的耦合度其实很高。比如如果我想做一个不加糖的美式咖啡,必须要重写一个子类。

  • 类爆炸?

  • 没错,我们做到了!实际子类的数量就可以达到N(咖啡品种)xM(额外添加物品种)的数量级。

来看桥接模式是怎么做的:

csharp 复制代码
public abstract class BaseCoffee{
    //关键步骤,将会引起某一维度变化的属性抽象为接口,子类中在引入抽象的具体实现
    protected CoffeeAdditive additive;

    public BaseCoffee(CoffeeAdditive additive){
        this.additive = additive;
    }
    public abstract void makeCoffee();
}

将add这一抽象方法,放在一个接口里,让实现了该接口的类实现该方法。

csharp 复制代码
public interface CoffeeAdditive {
    public String add();
}

具体的添加实现类有:

typescript 复制代码
public class Lemon implements CoffeeAdditive{
    @Override
    public String add() {
        return "加柠檬";
    }
}
typescript 复制代码
public class Milk implements CoffeeAdditive{
    @Override
    public String add() {
        return "加奶";
    }
}
typescript 复制代码
public class Sugar implements CoffeeAdditive{
    @Override
    public String add() {
        return "加糖";
    }
}

那么现在来看,在M维度上,我们只增加了M个实现类对吧。 再来看另一个维度,原来的子类被我们改成如下:

scala 复制代码
public class AmericanCoffee extends BaseCoffee{
    public AmericanCoffee(CoffeeAdditive additive) {
        super(additive);
    }

    @Override
    public void makeCoffee() {
        System.out.println("美式咖啡" + this.additive.add());
    }
}

这时候的子类只需要实现makeCoffee这一方法就好,因为原来的add方法已经被CoffeeAdditive实现类,只需要无脑调用即可。如此,在N维度上我们也只增加了N个类。最终的实现类和子类只会有N+M个。 当在客户端调用时:

java 复制代码
public class Client {
    public static void main(String[] args) {
        AmericanCoffee americanCoffee = new AmericanCoffee(new Milk());
        americanCoffee.makeCoffee();

        Cappuccino cappuccino = new Cappuccino(new Sugar());
        cappuccino.makeCoffee();

    }
}
相关推荐
bobz9653 分钟前
virtio vs vfio
后端
Rexi35 分钟前
“Controller→Service→DAO”三层架构
后端
bobz9651 小时前
计算虚拟化的设计
后端
深圳蔓延科技1 小时前
Kafka的高性能之路
后端·kafka
Barcke1 小时前
深入浅出 Spring WebFlux:从核心原理到深度实战
后端
JuiceFS1 小时前
从 MLPerf Storage v2.0 看 AI 训练中的存储性能与扩展能力
运维·后端
大鸡腿同学1 小时前
Think with a farmer's mindset
后端
Moonbit1 小时前
用MoonBit开发一个C编译器
后端·编程语言·编译器
Reboot2 小时前
达梦数据库GROUP BY报错解决方法
后端
稻草人22222 小时前
java Excel 导出 ,如何实现八倍效率优化,以及代码分层,方法封装
后端·架构