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

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

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

让我们来举一个做咖啡为基础的场景说明一些问题: 假设我们的咖啡只有两个维度: 制作咖啡本身的流程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();

    }
}
相关推荐
用户81818706274616 小时前
第25章 Redis集群脑裂实录:一次真实故障复盘
java·后端
呃呃呃呃ex16 小时前
2026年古法编程的末法时代,如何评估自己完成迅速转行
前端·后端
EatFan16 小时前
从单体到模块化:我的 Spring Boot 项目为什么拆成 framework、module、server?
java·spring boot·后端
回家路上绕了弯16 小时前
Codex 与 ZCode 有什么区别?从开发工作流看 AI 编程工具怎么选
后端
Java内核笔记16 小时前
Spring Boot 4 可观测性源码剖析:OpenTelemetry 全链路打通日志、指标、追踪
java·后端
学渣超16 小时前
从一次早高峰数据库告警说起:你真的理解缓存该如何落地应用吗?
redis·后端·架构
中趴菜16 小时前
接口返回的JSON为什么有反斜杠
后端
Bs_MoneyMagnet16 小时前
基于springboot+vue的在线音乐管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring