一起来学设计模式之适配器模式

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 前言目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~本节给大家讲一下设计模式中的适配器模式,并结合实际业务场景给大家讲解如何使用~本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~适配器模式适配器模式是一种结构型设计模式,其主要目的是将一个类的接口转换为另一个接口,以满足不同类之间的兼容性。

前言

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

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

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

适配器模式

适配器模式是一种结构型设计模式,其主要目的是将一个类的接口转换为另一个接口,以满足不同类之间的兼容性

适配器模式涉及到以下角色:

  • 目标接口(Target):这是客户端代码想要使用的接口,但它与客户端代码原本持有的接口不同。
  • 源接口(Adaptee):这是客户端代码原本持有的接口,但它与目标接口不兼容。
  • 适配器(Adapter):这是一个转换器,将源接口转换为目标接口。

适配器模式可以分为两种类型:类适配器对象适配器

  • 类适配器:通过继承源接口和目标接口来实现适配器。这种方式要求源接口必须是一个类而不是一个接口,因此不太常用。
  • 对象适配器:通过持有一个源接口实例和目标接口实例来实现适配器。这种方式可以适用于源接口是一个接口或类的情况。

下面我们来看一个对象适配器的例子,假设我们有一个第三方库,它提供了一个名为 ThirdPartyLibrary 的类,该类的接口如下:

public class ThirdPartyLibrary {
    public void doSomethingElse(int value) {
        System.out.println("Doing something else with value: " + value);
    }
}

而我们的客户端代码中使用的是一个名为 OurLibraryInterface 的接口,其接口如下:

public interface OurLibraryInterface {
    void doSomething(int value);
}

我们现在需要将ThirdPartyLibrary的接口转换为 OurLibraryInterface 的接口,以便在客户端代码中使用。

我们可以通过对象适配器模式来实现这一目标。首先,我们定义一个适配器类 ThirdPartyLibraryAdapter,该类实现了 OurLibraryInterface 接口,并持有一个 ThirdPartyLibrary 实例:

接着,我们在客户端代码中创建一个 ThirdPartyLibrary 的实例,并使用适配器类 ThirdPartyLibraryAdapter 将其转换为 OurLibraryInterface 的接口:

public class AdapterTest {
    public static void main(String[] args) {
        // 创建第三方库实例
        ThirdPartyLibrary library = new ThirdPartyLibrary();
        // 创建适配器实例
        OurLibraryInterface adapter = new ThirdPartyLibraryAdapter(library);
        // 在客户端代码中使用适配器
        adapter.doSomething(42);
    }
}

在上面的示例中,我们创建了一个 ThirdPartyLibrary 的实例,并通过适配器类 ThirdPartyLibraryAdapter 将其转换为 OurLibraryInterface 的接口。然后我们在客户端代码中使用适配器实例调用了 doSomething 方法,该方法实际上是调用了 ThirdPartyLibrarydoSomethingElse 方法。通过适配器模式,我们成功地将第三方库的接口转换为了客户端代码需要的接口,使得客户端代码能够正常工作。

适配器模式在实际开发中经常被使用,特别是在集成不同系统或库时。例如,我们可能需要将一个旧的库或系统接口转换为新的接口,以便与现有的代码进行交互。适配器模式可以帮助我们快速地完成这种转换工作,提高代码的复用性和可维护性。

最佳实践

同样以电商平台为例,假设我们的电商平台需要集成多个不同的第三方物流服务提供商,这些物流服务提供商的接口不一致,我们可以使用适配器模式来统一物流服务接口,使得我们的电商平台可以适配多种物流服务提供商。具体实现代码如下:

首先,我们定义一个 LogisticsService 接口,包含了电商平台需要的物流服务功能:

public interface LogisticsService {
    void createOrder(String orderId, String senderAddress, String receiverAddress);
    void cancelOrder(String orderId);
    void queryOrder(String orderId);
}

然后,我们创建一个适配器接口 LogisticsServiceAdapter,它用于适配不同的物流服务提供商接口:

public interface LogisticsServiceAdapter {
    void createOrder(String orderId, String senderAddress, String receiverAddress);
    void cancelOrder(String orderId);
    void queryOrder(String orderId);
}

接着,我们创建多个不同的物流服务提供商接口实现类:

  • 顺丰物流
public class SFExpressService {
    public void createShipment(String orderId, String senderAddress, String receiverAddress) {
        System.out.println("SF Express created shipment for order " + orderId + " from " + senderAddress + " to " + receiverAddress);
    }
    public void cancelShipment(String orderId) {
        System.out.println("SF Express cancelled shipment for order " + orderId);
    }
    public void queryShipment(String orderId) {
        System.out.println("SF Express queried shipment for order " + orderId);
    }
}
  • 韵达物流
public class YundaExpressService {
    public void createOrder(String orderId, String senderAddress, String receiverAddress) {
        System.out.println("Yunda Express created order for " + orderId + " from " + senderAddress + " to " + receiverAddress);
    }
    public void cancelOrder(String orderId) {
        System.out.println("Yunda Express cancelled order for " + orderId);
    }
    public void getOrderStatus(String orderId) {
        System.out.println("Yunda Express queried order status for " + orderId);
    }
}

接着,我们创建适配器类 SFExpressServiceAdapter,它封装了顺丰快递的接口,并将其转换为 LogisticsServiceAdapter 接口的实现:


public class SFExpressServiceAdapter implements LogisticsServiceAdapter {
    private SFExpressService sfExpressService;
    public SFExpressServiceAdapter(SFExpressService sfExpressService) {
        this.sfExpressService = sfExpressService;
    }
    @Override
    public void createOrder(String orderId, String senderAddress, String receiverAddress) {
        sfExpressService.createShipment(orderId, senderAddress, receiverAddress);
    }
    @Override
    public void cancelOrder(String orderId) {
        sfExpressService.cancelShipment(orderId);
    }
    @Override
    public void queryOrder(String orderId) {
        sfExpressService.queryShipment(orderId);
    }
}

同样的韵达也是这样:

public class YundaExpressServiceAdapter implements LogisticsServiceAdapter {
    private YundaExpressService yundaService;
    public YundaExpressServiceAdapter(YundaExpressService yundaService) {
        this.yundaService = yundaService;
    }
    @Override
    public void createOrder(String orderId, String senderAddress, String receiverAddress) {
        yundaService.createOrder(orderId, senderAddress, receiverAddress);
    }
    @Override
    public void cancelOrder(String orderId) {
        yundaService.cancelOrder(orderId);
    }
    @Override
    public void queryOrder(String orderId) {
        yundaService.getOrderStatus(orderId);
    }
}

最后我们实现物流平台的功能服务,对其接口进行封装

public class LogisticsPlatformService implements LogisticsService{
    private LogisticsServiceAdapter logisticsServiceAdapter;
    public LogisticsPlatformService(LogisticsServiceAdapter logisticsServiceAdapter) {
        this.logisticsServiceAdapter = logisticsServiceAdapter;
    }
    @Override
    public void createOrder(String orderId, String senderAddress, String receiverAddress) {
        logisticsServiceAdapter.createOrder(orderId, senderAddress, receiverAddress);
    }
    @Override
    public void cancelOrder(String orderId) {
        logisticsServiceAdapter.cancelOrder(orderId);
    }
    @Override
    public void queryOrder(String orderId) {
        logisticsServiceAdapter.queryOrder(orderId);
    }
}

接着,测试一下:

public class LogisticsPlatformServiceTest {
    public static void main(String[] args) throws Exception {
        SFExpressService sfExpressService = new SFExpressService();
        LogisticsServiceAdapter sfAdapter = new SFExpressServiceAdapter(sfExpressService);
        LogisticsService service = new LogisticsPlatformService(sfAdapter);
        service.cancelOrder("顺丰订单取消");
    }
}

输出:

SF Express cancelled shipment for order 顺丰订单取消

需要注意的是,在使用适配器模式时,应该尽量避免出现大量的嵌套适配器。如果需要多次适配,建议对原接口进行重构,尽量减少适配器的使用次数,以提高代码的可维护性和可读性。

结束语

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

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

相关文章

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

Kafka 专题学习

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

ElasticSearch 专题学习

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

往期并发编程内容推荐

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

博客(阅读体验较佳)




相关文章
|
6月前
|
设计模式 前端开发 Java
【设计模式】【结构型模式】适配器模式(Adpter)
一、入门 什么是适配器模式? 适配器模式是Java中常用的结构型设计模式,它的核心作用就像现实中的电源转换器一样---让原本不兼容的两个接口能够协同工作。 为什么要用适配器模式? 假设我们需要在电商系
167 10
|
10月前
|
设计模式 Java 开发者
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
355 28
|
设计模式 Java
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
|
11月前
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
设计模式 Java 程序员
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
107 2
|
设计模式 Java
Java设计模式之适配器模式
这篇文章详细讲解了Java设计模式中的适配器模式,包括其应用场景、实现方式及代码示例。
222 0
|
设计模式 XML 存储
【六】设计模式~~~结构型模式~~~适配器模式(Java)
文章详细介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成客户期望的另一个接口,使原本不兼容的接口能够一起工作,提高了类的复用性和系统的灵活性。通过对象适配器和类适配器两种实现方式,展示了适配器模式的代码应用,并讨论了其优点、缺点以及适用场景。
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
设计模式
适配器模式-大话设计模式
适配器模式-大话设计模式
|
设计模式 Go 数据处理
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式

热门文章

最新文章

下一篇
oss云网关配置