设计模式-适配器模式

设计模式专栏


模式介绍

适配器模式是一种结构型设计模式,它用于将一个接口转换成客户端所期望的另一个接口,使原本由于接口不兼容而不能一起工作的类能够一起工作。适配器模式可以用来解决旧接口与新接口不兼容、多个类的接口不一致以及一个类的接口需要与其它类一起使用但接口不兼容的问题。

适配器模式包含以下角色:

  1. 目标接口:客户端所期望的接口,它定义了客户端可以调用的方法。
  2. 适配器:将被适配者的接口转换成目标接口的中间件,它实现了目标接口,并持有一个被适配者的对象。
  3. 被适配者:客户端所需要的对象,但它的接口与目标接口不兼容。

适配器模式的应用场景非常广泛,例如在实际开发中,经常用于将旧的接口转换成新的接口,或者将多个类的接口转换成一个统一的接口。在使用适配器模式时,应该注意保持接口的一致性和简洁性,从而让代码更加易于维护和扩展。

适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种。在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。

在这里插入图片描述

主要特点

适配器模式具有以下优点:

  1. 提高类的透明性和复用性:适配器模式可以将一个类的接口转换成客户端所期待的另一种接口,使得客户端可以透明地调用目标接口,而无需关注适配的过程。同时,适配器模式还可以实现对现有类的复用,无需修改原有代码。
  2. 降低系统的耦合度:适配器模式通过引入适配器类来解耦目标类和适配类之间的关系,使得它们可以独立地扩展和变化,提高系统的可扩展性和可维护性。
  3. 符合开闭原则:适配器模式可以实现对现有类的复用,通过编写新的适配器类来实现适配,无需修改原有代码,符合开闭原则。

然而,适配器模式也存在以下缺点:

  1. 适配器编写过程需要全面考虑,可能会增加系统的复杂性。
  2. 适配器模式可能会增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
  3. 适配器模式可能会导致代码重复,如果一个接口需要适配多次,那么就需要编写多个适配器类,增加代码的维护难度。

适配器模式是一种非常实用的设计模式,它可以解决因接口不兼容而无法一起工作的两个类的问题,同时也可以提供更好的可复用性和可扩展性。然而,在应用适配器模式时需要注意其缺点,并合理控制使用范围。

在这里插入图片描述

应用场景

适配器模式的应用场景包括但不限于以下几种情况:

    1. 系统需要使用现有的类,而此类的接口不符合需要。
    1. 需要一个统一的输出接口,而输入类型不可预知。例如在Android中的Adapter。
    1. 创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类协同工作。例如在Android中的Adapter。
    1. 已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。

一个适配器模式的实际应用例子是手机充电器。我们可以将220V交流电看作是被适配者,而5V直流电则是目标接口。适配器模式在这里的应用是将220V交流电适配成5V直流电,使得手机等设备可以使用适配后的电源进行充电。这个例子中,适配器(VoltageAdapter)继承了220V交流电的类(Voltage220V),并实现了目标接口(IVoltage5V),从而使得手机等设备可以透明地调用目标接口,使用适配后的电源进行充电。这个例子展示了适配器模式如何将不兼容的接口转换成客户端所期望的接口,使原本由于接口不兼容而不能一起工作的类能够一起工作。

在这里插入图片描述

模式背景与原理

适配器模式的背景是在软件开发中,经常需要将不同的类组合在一起使用,但是有些类的接口可能与其它类的接口不兼容,导致这些类无法一起工作。为了解决这个问题,适配器模式提供了一种解决方案,即将一个类的接口转换成客户端所期待的另一种接口,从而使这些类能够一起工作。

适配器模式的基本原理是将一个类的接口转换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够一起工作。适配器模式的核心思想是将一个类的接口转换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够一起工作。这个过程是通过适配器类来实现的,适配器类实现了目标接口,并将被适配者的对象作为成员变量,通过调用被适配者的相关接口方法来实现目标接口方法。

适配器模式包括三种形式:类适配器模式对象适配器模式接口适配器模式。类适配器模式是将被适配者的子类与目标接口的子类进行适配;对象适配器模式是将被适配者对象与目标接口对象进行适配;接口适配器模式是将被适配者的接口与目标接口的子类进行适配。

适配器模式的应用场景非常广泛,例如在电力系统中,需要将交流电转换成直流电;在音频系统中,需要将不同格式的音频文件转换成相同的格式;在数据库系统中,需要将不同的数据库系统转换成相同的数据库接口等等。

适配器模式是一种非常实用的设计模式,它可以解决因接口不兼容而无法一起工作的两个类的问题,同时也可以提供更好的可复用性和可扩展性。

在这里插入图片描述

代码示例

Java实现适配器模式

以下是一个使用Java实现的适配器模式的代码示例:

假设我们有一个旧的音频播放器接口 OldAudioPlayer 和一个新的音频播放器接口 NewAudioPlayer,但是新的音频播放器接口不兼容旧的音频文件格式。我们需要创建一个适配器来将旧的音频文件格式转换为新的音频播放器接口可以处理的格式。

// 旧的音频播放器接口
interface OldAudioPlayer {
   
    void playOldAudio(String fileName);
}

// 新的音频播放器接口
interface NewAudioPlayer {
   
    void playNewAudio(String fileName);
}

// 旧的音频播放器实现类
class OldAudioPlayerImpl implements OldAudioPlayer {
   
    @Override
    public void playOldAudio(String fileName) {
   
        System.out.println("Playing old audio file: " + fileName);
    }
}

// 新的音频播放器实现类
class NewAudioPlayerImpl implements NewAudioPlayer {
   
    @Override
    public void playNewAudio(String fileName) {
   
        System.out.println("Playing new audio file: " + fileName);
    }
}

// 适配器类,实现了新的音频播放器接口,并持有一个旧的音频播放器对象
class AudioAdapter implements NewAudioPlayer {
   
    private OldAudioPlayer oldAudioPlayer;

    public AudioAdapter(OldAudioPlayer oldAudioPlayer) {
   
        this.oldAudioPlayer = oldAudioPlayer;
    }

    @Override
    public void playNewAudio(String fileName) {
   
        oldAudioPlayer.playOldAudio(fileName);
    }
}

// 客户端代码,使用适配器来播放旧的音频文件格式
public class Client {
   
    public static void main(String[] args) {
   
        OldAudioPlayer oldAudioPlayer = new OldAudioPlayerImpl();
        NewAudioPlayer newAudioPlayer = new AudioAdapter(oldAudioPlayer);
        newAudioPlayer.playNewAudio("old_audio_file.mp3"); // 输出 "Playing old audio file: old_audio_file.mp3"
    }
}

在这个示例中,我们创建了一个适配器类 AudioAdapter,它实现了新的音频播放器接口 NewAudioPlayer,并持有一个旧的音频播放器对象 OldAudioPlayer。在适配器类的 playNewAudio() 方法中,我们调用了旧的音频播放器对象的 playOldAudio() 方法来播放旧的音频文件格式。在客户端代码中,我们创建了一个旧的音频播放器对象和一个适配器对象,并使用适配器对象来播放旧的音频文件格式。适配器模式使得客户端代码可以透明地使用新的音频播放器接口来播放旧的音频文件格式。

Python实现适配器模式

在Python中实现适配器模式可以使用类的继承或对象的组合来实现。下面是一个使用对象组合实现适配器模式的示例代码:

class Target:
    def request(self):
        print("Target request")

class Adaptee:
    def specific_request(self):
        print("Adaptee specific request")

class Adapter(Target):
    def __init__(self):
        self.adaptee = Adaptee()
    
    def request(self):
        print("Adapter request")
        self.adaptee.specific_request()

if __name__ == "__main__":
    target = Target()
    target.request()
    
    adapter = Adapter()
    adapter.request()

在上面的代码中,我们定义了一个Target接口,其中包含一个request方法。我们还定义了一个Adaptee类,它有一个特定的方法specific_request。我们的目标是让Adaptee类能够适配到Target接口,以便我们可以将Adaptee对象当作Target对象来使用。

为了实现这个目标,我们定义了一个Adapter类,它继承自Target接口,并包含一个adaptee属性,它是一个Adaptee对象。在Adapter类的request方法中,我们调用了adapteespecific_request方法来实现适配。现在我们可以将Adapter对象当作Target对象来使用,并且可以调用request方法来执行Adaptee的特定请求。

在上面的示例中,我们创建了一个Target对象和一个Adapter对象,并分别调用了它们的request方法。输出结果如下:

Target request
Adapter request
Adaptee specific request

在这里插入图片描述

适配器模式在spring中的应用

适配器模式在Spring框架中有着广泛的应用。例如,在Spring的AOP(面向切面编程)模块中,适配器模式被用来实现各种不同的切面。

具体来说,Spring AOP使用适配器模式来适配不同的通知类型。例如,前置通知(BeforeAdvice)和后置通知(AfterAdvice)需要适配到目标方法(TargetMethod)上,异常通知(AfterThrowingAdvice)需要适配到目标异常(TargetException)上。这些通知类型通过适配器模式来统一接口,以便于Spring AOP模块能够统一处理。

此外,在Spring的ORM模块中,适配器模式也被用来适配不同的数据访问技术,如JDBC、Hibernate、MyBatis等。这些数据访问技术都有自己特定的接口,但是通过适配器模式可以将它们统一为一种通用的接口,使得在使用不同的数据访问技术时,代码的编写方式可以保持一致。

适配器模式在Spring框架中有着广泛的应用,它可以帮助Spring框架更好地支持各种不同的技术和接口,提高框架的灵活性和可扩展性。

在这里插入图片描述

设计模式-原型模式

设计模式-建造者模式

设计模式-工厂模式

设计模式-单例模式

设计模式-适配器模式

设计模式-装饰器模式

相关推荐

  1. 设计模式适配器模式

    2023-12-08 14:14:01       45 阅读
  2. 设计模式——适配器模式

    2023-12-08 14:14:01       34 阅读
  3. 设计模式-适配器模式

    2023-12-08 14:14:01       29 阅读
  4. 设计模式——适配器模式

    2023-12-08 14:14:01       27 阅读
  5. 设计模式-适配器模式

    2023-12-08 14:14:01       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-08 14:14:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-08 14:14:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-08 14:14:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-08 14:14:01       20 阅读

热门阅读

  1. Linux篇之基于Centos的everything镜像搭建yum镜像源

    2023-12-08 14:14:01       37 阅读
  2. WordPress禁止显示指定类别的文章

    2023-12-08 14:14:01       40 阅读
  3. Elasticsearch桶聚合和管道聚合

    2023-12-08 14:14:01       33 阅读
  4. Docker

    Docker

    2023-12-08 14:14:01      45 阅读
  5. 超详细数学建模论文模板分享

    2023-12-08 14:14:01       32 阅读