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

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

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

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

    }
}
相关推荐
MemoleCard11 小时前
深度解析Java当中的锁机制
后端
wear工程师11 小时前
ThreadLocal 在线程池里为什么会串数据:别只会答内存泄漏
java·后端
whyfail11 小时前
前端学 Spring Boot(2):一次点击,如何穿过整个后端?
前端·spring boot·后端
程序员cxuan13 小时前
Loop 还没玩明白,Graph Engineering 又火了。
人工智能·后端·程序员
uzong14 小时前
把一面面试总结做成一个 Skill:重复的事,就别每次都重写
后端·面试
程序员海军15 小时前
一个 AI 应用开发程序员的一天,都在屏幕前忙些什么?
前端·后端·程序员
不能放弃治疗15 小时前
MCP
后端
江湖十年16 小时前
Go 语言中 YAML to JSON 踩坑笔记
后端·go·json
你驴我17 小时前
WhatsApp 消息撤回与编辑的幂等性设计实践
java·服务器·前端·后端·python