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

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

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

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

    }
}
相关推荐
咖啡八杯3 小时前
GoF设计模式——策略模式
java·后端·spring·设计模式
lizhongxuan4 小时前
AI Agent 上下文压缩利器 Headroom
后端
Csvn6 小时前
SSH 远程管理与安全加固 — 运维的守门之道
后端
IT_陈寒6 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
菜鸟谢7 小时前
Rust 智能指针完整详解
后端
菜鸟谢8 小时前
Rust 函数完整知识点详解
后端
爱勇宝8 小时前
淡泊名利之前,先承认我们都很焦虑
前端·后端·程序员
菜鸟谢8 小时前
Rust 闭包(Closure)完整详解
后端
ServBay8 小时前
如何利用本地技术栈构建 0 成本 AI SaaS 雏形
后端·aigc·ai编程
菜鸟谢8 小时前
Rust 集合 + 迭代器完整详解
后端