一起来学设计模式之桥接模式

前言

目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

本节给大家讲一下设计模式中的桥接模式,并结合实际业务场景给大家讲解如何使用~

本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~

桥接模式

桥接模式(Bridge Pattern)``是一种结构型设计模式,用于将抽象部分实现部分`分离开来,从而使它们可以独立地进行变化。这种模式通过将抽象部分与实现部分解耦,使得它们可以独立地进行扩展、修改和重用。

在桥接模式中,抽象部分和实现部分分别由两个层次结构来实现。抽象部分定义了对外提供的接口和方法,而实现部分则提供了具体的实现细节。通过将抽象部分和实现部分解耦,我们可以在不影响系统稳定性的前提下对其进行修改和扩展。

举个例子,假设我们正在开发一个跨平台的音乐播放器,它可以在 Windows、Mac、Linux 等多种操作系统上运行。由于不同的操作系统之间存在很大的差异,因此我们需要针对每种操作系统编写不同的实现代码。在这种情况下,我们可以使用桥接模式来将抽象部分和实现部分分离开来。

首先,我们定义一个抽象类 MediaPlayer,它定义了播放器的基本接口和方法:

public abstract class MediaPlayer {
    protected OperatingSystem operatingSystem;

    public MediaPlayer(OperatingSystem operatingSystem) {
        this.operatingSystem = operatingSystem;
    }

    public abstract void play();
}
复制代码

其中,OperatingSystem 是一个抽象类,定义了不同操作系统之间的共同特征:

public abstract class OperatingSystem {
    public abstract String getName();
}

复制代码

接下来,我们定义不同操作系统的具体实现类,例如 Windows、Mac 和 Linux

public class Windows extends OperatingSystem {
    @Override
    public String getName() {
        return "Windows";
    }
}

public class Mac extends OperatingSystem {
    @Override
    public String getName() {
        return "Mac";
    }
}

public class Linux extends OperatingSystem {
    @Override
    public String getName() {
        return "Linux";
    }
}

复制代码

最后,我们定义不同操作系统下的具体播放器实现类,例如 WindowsMediaPlayer、MacMediaPlayer 和 LinuxMediaPlayer

public class WindowsMediaPlayer extends MediaPlayer {
    public WindowsMediaPlayer(OperatingSystem operatingSystem) {
        super(operatingSystem);
    }

    @Override
    public void play() {
        System.out.println("Playing on " + operatingSystem.getName() + " using WindowsMediaPlayer.");
    }
}

public class MacMediaPlayer extends MediaPlayer {
    public MacMediaPlayer(OperatingSystem operatingSystem) {
        super(operatingSystem);
    }

    @Override
    public void play() {
        System.out.println("Playing on " + operatingSystem.getName() + " using MacMediaPlayer.");
    }
}

public class LinuxMediaPlayer extends MediaPlayer {
    public LinuxMediaPlayer(OperatingSystem operatingSystem) {
        super(operatingSystem);
    }

    @Override
    public void play() {
        System.out.println("Playing on " + operatingSystem.getName() + " using LinuxMediaPlayer.");
    }
}
复制代码

比如在mac平台下可以这么调用

public class BridgeTest {
    public static void main(String[] args) {
        MediaPlayer player = new MacMediaPlayer(new Mac());
        player.play();

        // Playing on Mac using MacMediaPlayer.
    }
}
复制代码

桥接模式的优点有:

  • 提高可扩展性:桥接模式将抽象部分与实现部分分离,使它们可以分别变化。这样,当增加一个新的实现时,就不需要修改抽象部分和其他实现部分了,只需要添加一个新的实现即可。

  • 降低耦合度:桥接模式将抽象部分与实现部分分离,使它们可以独立变化,从而降低了它们之间的耦合度。这使得系统更易于维护和扩展。

  • 更好的分离抽象与实现:桥接模式提供了一个更好的分离抽象与实现的方式,使得抽象与实现可以独立变化。这使得系统更具灵活性、可扩展性和可维护性。

是不是比你if/else好太多~

最佳实践

假设我们正在开发一个电商平台,以下是订单处理的桥接模式的实现:

首先,定义一个抽象类 Order,它有一个抽象方法 process()

public abstract class Order {
    protected OrderProcessor orderProcessor;

    public Order(OrderProcessor orderProcessor) {
        this.orderProcessor = orderProcessor;
    }

    public abstract void process();
}
复制代码

然后,定义两个具体的订单类 NormalOrderRushOrder,它们继承自 Order

public class NormalOrder extends Order {
    public NormalOrder(OrderProcessor orderProcessor) {
        super(orderProcessor);
    }

    @Override
    public void process() {
        orderProcessor.processNormalOrder();
    }
}

public class RushOrder extends Order {
    public RushOrder(OrderProcessor orderProcessor) {
        super(orderProcessor);
    }

    @Override
    public void process() {
        orderProcessor.processRushOrder();
    }
}

复制代码

接下来,定义一个抽象类 OrderProcessor,它有两个抽象方法 processNormalOrder()processRushOrder()

public abstract class OrderProcessor {
    public abstract void processNormalOrder();
    public abstract void processRushOrder();
}

复制代码

然后,定义两个具体的订单处理类 OnlineOrderProcessorOfflineOrderProcessor,它们继承自 OrderProcessor

public class OnlineOrderProcessor extends OrderProcessor {
    @Override
    public void processNormalOrder() {
        System.out.println("在线订单处理普通订单");
    }

    @Override
    public void processRushOrder() {
        System.out.println("在线订单处理加急订单");
    }
}


public class OfflineOrderProcessor extends OrderProcessor {
    @Override
    public void processNormalOrder() {
        System.out.println("线下订单处理普通订单");
    }

    @Override
    public void processRushOrder() {
        System.out.println("线下订单处理加急订单");
    }
}
复制代码

最后,在客户端中,可以根据需要创建不同的订单对象和订单处理对象,并将它们桥接起来:

public class BridgeTest {
    public static void main(String[] args) throws Exception {
        OrderProcessor onlineOrderProcessor = new OnlineOrderProcessor();
        OrderProcessor offlineOrderProcessor = new OfflineOrderProcessor();

        Order normalOnlineOrder = new NormalOrder(onlineOrderProcessor);
        Order rushOnlineOrder = new RushOrder(onlineOrderProcessor);
        Order normalOfflineOrder = new NormalOrder(offlineOrderProcessor);
        Order rushOfflineOrder = new RushOrder(offlineOrderProcessor);

        normalOnlineOrder.process();
        rushOnlineOrder.process();
        normalOfflineOrder.process();
        rushOfflineOrder.process();
    }
}

复制代码

输出:

在线订单处理普通订单
在线订单处理加急订单
线下订单处理普通订单
线下订单处理加急订单

复制代码

结束语

设计模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。下节给大家讲组合模式~

本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注鼓励一下呗~

相关文章

项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)

猜你喜欢

转载自juejin.im/post/7218743537495113788