欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 设计模式——Adapter(适配器)模式

设计模式——Adapter(适配器)模式

2025/6/27 13:19:02 来源:https://blog.csdn.net/weixin_41605937/article/details/144334556  浏览:    关键词:设计模式——Adapter(适配器)模式

摘要

本文介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成另一个接口以实现类之间的协同工作。文章详细阐述了适配器模式的定义、类型、作用、优点,并提供了使用场景和Spring框架下的示例代码。适配器模式通过解耦和扩展性,提高了系统的灵活性和可维护性。

1. 适配器模式是什么

1.1. 适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成客户端所期待的另一个接口。适配器模式使得原本接口不兼容的类能够一起工作,常用于集成现有系统和服务,或者将不同接口的数据进行转换。适配器模式的核心优势是解耦和扩展性通过引入适配器层,我们可以在不改变现有系统代码的前提下,让不同接口的类协同工作,从而提高系统的灵活性和可维护性。

适配器模式的类型

  1. 类适配器(Class Adapter):通过继承原有类来实现适配。
  2. 对象适配器(Object Adapter):通过组合已有类的实例来实现适配。

适配器模式通过引入适配器层(AliPayAdapterWeChatPayAdapter),成功实现了类之间的依赖解耦:

  1. 客户端(PaymentProcessor)不依赖具体的支付实现类,而是依赖于抽象的 PaymentService 接口。
  2. 支付服务的具体实现(如 AliPayServiceWeChatPayService)通过适配器暴露出统一的接口,使得客户端能够透明地切换不同的支付方式。
  3. 通过 Spring的依赖注入,适配器层(AliPayAdapterWeChatPayAdapter)被注入到客户端中,进一步解耦了类与类之间的依赖关系。

这种方式使得系统更容易扩展和维护,因为你可以轻松添加新的支付方式,只需编写新的适配器类,而不需要修改已有的客户端代码。

1.2. 适配器模式作用

适配器模式的作用:

  • 接口转换,将原有的接口(或方法)转换成另一种接口;
  • 用新的接口包装一个已有的类;
  • 匹配一个老的组件到一个新的接口。

1.3. 适配器模式的优点

  • 可以让两个没有关联的类一起运行,起着中间转换的作用。
  • 提高了类的复用。
  • 灵活性好,不会破坏原有的系统。

1.4. 适配器模式的缺点

  • 如果原有系统没有设计好(如 Target 不是抽象类或接口,而一个实体类),适配器模式将很难实现。
  • 过多地使用适配器,容易使代码结构混乱,如明明看到调用的是 A 接口,内部调用的却是 B 接口的实现。

2. 适配器模式类图

Target 是一个接口类,是提供给用户调用的接口抽象,如上面示例中的 IHightPerson。Adaptee 是你要进行适配的对象类,如上面的 ShortPerson。Adapter 是一个适配器,是对 Adaptee 的适配,它将 Adaptee 的对象转换(或说包装)成符合 Target 接口的对象;如上面的 DecoratePerson,将 ShortPerson 的 getRealHeight 和 getShoesHeight 方法包装成 IHightPerson 的 getHeight 接口。

设计要点:适配器模式中主要三个角色,在设计适配器模式时要找到并区分这些角色:

  • 目标(Target): 即你期望的目标接口,要转换成的接口。
  • 源对象(Adaptee): 即要被转换的角色,要把谁转换成目标角色。
  • 适配器(Adapter): 适配器模式的核心角色,负责把源对象转换和包装成目标对象。

3. 适配器模式使用场景

3.1. 接口不兼容的情况下

场景描述:当两个现有类的接口不兼容,但它们必须协作时,可以使用适配器模式。通过适配器模式,我们可以将一个类的接口转换成另一个类所期望的接口,从而实现它们的兼容性。

示例:假设你有一个老旧的系统,它通过某个接口处理支付,而你现在需要将其与一个新的支付系统集成,这两个系统的接口不兼容。你可以使用适配器模式将老旧支付系统的接口转换成新支付系统的接口

3.2. 复用现有系统或类

场景描述:当现有系统或者第三方库的接口不符合当前需求时,你可以使用适配器模式将其转换为符合当前需求的接口,避免修改现有代码并在新环境中复用它们。

示例:假设你正在使用一个老旧的数据库访问类库,它的接口无法满足你当前的框架要求。你可以通过适配器模式,将数据库访问类库的接口适配成当前框架需要的接口,从而在不修改原有代码的前提下进行复用。

3.3. 整合多个不同的接口

场景描述:当你需要整合多个不同的接口时,适配器模式可以帮助你统一这些接口,从而使客户端能够以一致的方式进行操作。

示例:假设你有多个支付服务提供商,每个提供商的接口不同,但你希望通过统一的方式来调用这些支付服务。你可以为每个支付服务编写适配器,使其都实现统一的 PaymentService 接口。客户端只需要调用 PaymentService 接口,而无需关心具体支付服务的实现。

3.4. 不可修改的接口或类

场景描述:有些类或系统的接口不可修改,特别是第三方库或遗留系统的接口。这时候,适配器模式非常有用,可以帮助你将这些接口适配到系统所需要的接口。

示例:你有一个遗留系统,它的接口无法修改,而你的新系统需要与这个遗留系统进行集成。通过适配器模式,你可以将遗留系统的接口适配到新系统的接口需求上,而不需要修改遗留系统的代码。

3.5. 接口需要扩展但不修改原有代码

场景描述:当你需要扩展现有接口的功能,而又不希望直接修改现有代码时,适配器模式是一个不错的选择。适配器可以在不修改现有类的情况下为其提供额外的功能。

示例:你正在使用一个图形库,它有一些方法非常适合你的需求,但你需要在其基础上添加额外的功能(例如日志记录或性能监控)。你可以通过编写一个适配器类,来扩展该图形库的功能,而不修改库本身的代码。

3.6. 系统的逐步升级和迁移

场景描述:当系统需要逐步升级或迁移时,适配器模式可以帮助你在过渡阶段保持系统的兼容性,避免一次性改变所有接口。

示例:假设你正在将一个系统从一个老旧的技术栈迁移到一个新的技术栈。在迁移过程中,可能有一些模块是无法立即替换的,这时候你可以使用适配器模式将新的模块与旧的模块连接起来,确保迁移过程中的兼容性。

3.7. 实现第三方库的统一接口

场景描述:当使用多个第三方库时,每个库可能有不同的接口,适配器模式能够将这些不同的接口适配成统一的接口,简化系统的调用。

示例:假设你正在使用多个支付SDK,每个SDK的支付接口不同,且你的系统希望统一调用这些接口。在这种情况下,你可以为每个支付SDK编写适配器类,使得它们实现相同的支付接口,从而在客户端统一调用。

3.8. 需要对现有类进行包装和增强

场景描述:适配器不仅可以转换接口,还可以增强原有功能,比如日志、权限检查、性能监控等。适配器模式非常适合用来增加一些额外的功能,包装现有的类。

示例:假设你有一个简单的日志记录系统,系统中有很多日志记录的类,你希望为这些日志记录类添加额外的功能,比如性能监控、异常处理等。通过适配器,你可以为现有日志类添加这些功能,而不修改其原有实现。

4. 适配器模式示例(Spring)

在Spring中实现适配器模式时,我们通常会使用Spring的依赖注入(DI)来管理适配器的对象。下面是一个示例,展示如何通过Spring管理适配器对象并实现适配器模式。

4.1. 定义新支付接口

首先定义一个系统期望的支付接口 PaymentService,所有的支付服务(包括旧支付服务)都应该实现这个接口。

public interface PaymentService {void processPayment(String account, double amount);
}

4.2. 定义旧支付服务(LegacyPaymentService)

假设我们有一个老旧的支付服务,接口不符合我们现在的需求。

@Service
public class LegacyPaymentService {public void processLegacyPayment(String account, double amount) {System.out.println("Processing payment through legacy system...");System.out.println("Account: " + account + ", Amount: " + amount);}
}

4.3. 定义适配器类(LegacyPaymentAdapter)

我们通过一个适配器将旧的 LegacyPaymentService 适配到新的 PaymentService 接口。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class LegacyPaymentAdapter implements PaymentService {@Autowiredprivate LegacyPaymentService legacyPaymentService;@Overridepublic void processPayment(String account, double amount) {// 调用旧支付服务的方法legacyPaymentService.processLegacyPayment(account, amount);}
}

4.4. 定义支付处理类(PaymentProcessor)

我们定义一个 PaymentProcessor 类,它依赖于 PaymentService 接口。在Spring容器中,Spring会注入适配器类(LegacyPaymentAdapter),而不是直接注入 LegacyPaymentService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class PaymentProcessor {@Autowiredprivate PaymentService paymentService;public void processPayment(String account, double amount) {paymentService.processPayment(account, amount);}
}

博文参考

《软件设计模式》

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词