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

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 前言目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~本节给大家讲一下设计模式中的适配器模式,并结合实际业务场景给大家讲解如何使用~本专题的所有案例代码主要以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 API
重构旧代码的秘诀:用设计模式 - 适配器模式(Adapter)给Java项目带来新生
【4月更文挑战第7天】适配器模式是解决接口不兼容问题的结构型设计模式,通过引入适配器类实现目标接口并持有不兼容类引用,实现旧代码与新接口的协作。适用于处理兼容性问题、整合遗留代码和集成第三方库。应用时,识别不兼容接口,创建适配器类转换方法调用,然后替换原有引用。注意保持适配器简单、使用组合和考虑扩展性。过度使用可能导致系统复杂和维护成本增加,应谨慎使用。
100 4
|
6月前
|
设计模式 Java 中间件
23种设计模式,适配器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要目标是让原本由于接口不匹配而不能一起工作的类可以一起工作。适配器模式主要有两种形式:类适配器和对象适配器。类适配器模式通过继承来实现适配,而对象适配器模式则通过组合来实现
102 4
|
2月前
|
设计模式 Java 程序员
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
|
1月前
|
设计模式 Java
Java设计模式之适配器模式
这篇文章详细讲解了Java设计模式中的适配器模式,包括其应用场景、实现方式及代码示例。
40 0
|
6月前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
|
2月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
3月前
|
设计模式 XML 存储
【六】设计模式~~~结构型模式~~~适配器模式(Java)
文章详细介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成客户期望的另一个接口,使原本不兼容的接口能够一起工作,提高了类的复用性和系统的灵活性。通过对象适配器和类适配器两种实现方式,展示了适配器模式的代码应用,并讨论了其优点、缺点以及适用场景。
|
5月前
|
设计模式
适配器模式-大话设计模式
适配器模式-大话设计模式
|
4月前
|
设计模式 Go 数据处理
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
|
4月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 适配器模式
js设计模式【详解】—— 适配器模式
31 0

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    42
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    46
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    53
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    37
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    61
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    56
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    40
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    49
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    105
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    75