【设计模式】适配器模式

一、什么是适配器模式

概念:

  • 适配器模式是一种结构型设计模式,它将一个类的接口转换成客户端所期望的另一种接口,使得原本不兼容的类能够一起工作。适配器模式主要包括目标接口、适配器和被适配对象。目标接口定义了客户端所期望的接口,适配器实现目标接口,并持有被适配对象的引用,通过调用被适配对象的方法来完成目标接口的实现。

适配器模式的角色组成:

  1. 目标接口(Target Interface):目标接口是客户端所期望的接口,适配器模式将原始接口转换成目标接口,使得客户端可以通过目标接口来访问被适配对象。

  2. 适配器(Adapter):适配器是适配器模式的核心,它实现目标接口,并持有被适配对象的引用。适配器将客户端的请求转发给被适配对象,完成客户端所期望的功能。

  3. 被适配对象(Adaptee):被适配对象是需要被适配的类或接口,它包含了客户端所需要的功能。

适配器模式可以分为类适配器对象适配器两种形式,它们在适配器的实现方式上有所不同:

  • 类适配器:类适配器通过多重继承将适配器类(继承目标接口)与被适配类(被继承)连接起来,使得适配器具有被适配对象的功能。
  • 对象适配器:对象适配器通过持有被适配对象的引用,将客户端的请求转发给被适配对象,实现目标接口的功能。

无论是类适配器还是对象适配器,它们的目的都是将被适配对象的接口转换成客户端所期望的接口,实现接口的兼容性。

二、适配器模式的Java实现示例

类适配器实现(继承能力):

java 复制代码
// 目标接口
public interface Target {
    void request();
}

// 被适配对象
public class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee's specific request");
    }
}

// 适配器类(继承目标接口,同时持有被适配对象的引用)
public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        specificRequest();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Target target = new Adapter();
        target.request();
    }
}

对象适配器实现(引用能力):

java 复制代码
// 目标接口
public interface Target {
    void request();
}

// 被适配对象
public class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee's specific request");
    }
}

// 适配器类(实现目标接口,持有被适配对象的引用)
public class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}

以上是适配器模式的两种常见实现方式,它们分别使用了类继承和对象组合来实现适配器功能。根据具体的场景和需求选择适合的实现方式即可。

二、适配器模式的优点

  1. 代码复用性:适配器模式可以重复使用现有的类,通过适配器将其转换为目标接口,使得这些类可以在新的环境中复用。

  2. 系统可扩展性:适配器模式允许系统在不修改已有代码的情况下扩展功能,只需要新增适配器类即可。

  3. 统一接口:适配器模式可以将不同接口的类转换为统一的目标接口,从而统一了接口的使用方法,使得系统更加统一和一致。

  4. 解耦合性:适配器模式可以解耦已有类和目标接口之间的依赖关系,使得它们可以独立地进行演化和升级。

三、适配器模式的应用场景及示例

  1. 外部接口的适配: 当系统需要与外部的接口进行交互时,但外部接口的方法和系统内部定义的方法不一致,可以使用适配器模式将外部接口适配成系统需要的接口。
    例如,系统需要调用支付宝支付接口,但系统内部定义的支付接口和支付宝的接口不一致,可以通过编写一个支付宝支付适配器来适配两者之间的差异。

  2. 数据库适配: 当系统需要切换数据库或使用不同的数据库连接方式时,可以使用适配器模式进行数据库适配。
    例如,系统原来使用MySQL数据库,但需要切换到Oracle数据库,可以通过编写一个Oracle数据库适配器来适配两种不同的数据库。

  3. GUI界面适配: 当系统需要在不同的操作系统上运行,且每个操作系统的GUI界面不同,可以使用适配器模式进行GUI界面适配。
    例如,系统在Windows操作系统上运行时,需要使用Windows的GUI界面组件,而在Mac操作系统上运行时,需要使用Mac的GUI界面组件,可以通过编写不同操作系统的GUI适配器来适配不同的GUI界面。

  4. 日志适配: 当系统需要将日志输出到不同的日志系统,例如将日志同时输出到控制台和文件中,可以使用适配器模式进行日志适配。
    例如,系统原来使用log4j作为日志输出组件,但需要切换到logback作为日志输出组件,可以通过编写一个logback的适配器来适配两种不同的日志输出组件。

五、SpringBoot中适配器模式的实现

适配器模式在Spring Boot中的使用示例:第三方支付服务

java 复制代码
// 目标接口,定义了在业务中需要使用的方法
public interface PaymentService {
    void pay(String paymentType, double amount);
}

// 第三方支付服务类,提供了第三方支付功能
@Component
public class ThirdPartyPaymentService {
    public void makePayment(String type, double amount) {
        // 调用第三方支付服务的接口进行支付
        System.out.println("Making payment via " + type + ": $" + amount);
    }
}

// 适配器类,将第三方支付服务类适配为目标接口
@Component
public class PaymentServiceAdapter implements PaymentService {
    @Autowired
    private ThirdPartyPaymentService thirdPartyPaymentService;

    @Override
    public void pay(String paymentType, double amount) {
        // 调用第三方支付服务类的方法来完成支付
        thirdPartyPaymentService.makePayment(paymentType, amount);
    }
}

// 使用适配器模式进行支付
@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(Main.class, args);
        PaymentService paymentService = context.getBean(PaymentService.class);

        // 使用适配器进行支付
        paymentService.pay("Alipay", 100.0);
        paymentService.pay("WeChat Pay", 200.0);
    }
}

在这个示例中,我们使用Spring Boot来实现适配器模式。首先定义了目标接口PaymentService,其中定义了支付的方法。然后有一个第三方支付服务类ThirdPartyPaymentService,提供了第三方支付的功能,并且使用@Component注解将其声明为Spring Bean。

适配器类PaymentServiceAdapter同样使用@Component注解将其声明为Spring Bean,并使用@Autowired注解将ThirdPartyPaymentService注入其中。适配器类实现了目标接口,并将第三方支付服务类进行适配。

Main类中,我们使用@SpringBootApplication注解启动Spring Boot应用。通过ApplicationContext从Spring容器中获取PaymentService实例,然后使用适配器进行支付。

这个示例中的适配器模式应用于一个实际的业务场景,将第三方支付服务类适配为我们业务中需要的支付服务。同时,利用Spring Boot来管理和注入依赖,使得适配器模式的实现更加简洁和灵活。

相关推荐
书埋不住我14 分钟前
java第三章
java·开发语言·servlet
boy快快长大16 分钟前
将大模型生成数据存入Excel,并用增量的方式存入Excel
java·数据库·excel
孟秋与你19 分钟前
【spring】spring单例模式与锁对象作用域的分析
java·spring·单例模式
菜菜-plus23 分钟前
java 设计模式 模板方法模式
java·设计模式·模板方法模式
萨达大24 分钟前
23种设计模式-模板方法(Template Method)设计模式
java·c++·设计模式·软考·模板方法模式·软件设计师·行为型设计模式
tian-ming25 分钟前
(十八)JavaWeb后端开发案例——会话/yml/过滤器/拦截器
java·开发语言·前端
不能只会打代码29 分钟前
大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界
java·github·intellij-idea·话题博客
快意咖啡~35 分钟前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio
IT枫斗者1 小时前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网
爱编程的小生1 小时前
Easyexcel(4-模板文件)
java·excel