深入浅出设计模式 - 适配器模式

简介: 深入浅出设计模式 - 适配器模式

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

1687857236593.jpg

1、什么是适配器模式

适配器模式是一种结构型设计模式,它用于将一个类的接口转换成客户端所期望的另一个接口。适配器模式可以让原本由于接口不兼容而无法一起工作的类能够协同工作。

适配器模式的主要作用是解决两个已有接口之间的不兼容问题,以便它们能够协同工作。适配器模式有三种实现方式:类适配器、对象适配器和接口适配器。

类适配器是通过继承来实现的,它可以适配一个类的接口到另一个类的接口。对象适配器是通过组合来实现的,它可以适配一个对象的接口到另一个对象的接口。接口适配器是通过抽象类来实现的,它可以适配一个接口的部分方法到另一个接口。

适配器模式的优点是可以让原本不兼容的接口协同工作,提高代码的复用性和灵活性。缺点是可能会增加代码的复杂度和维护成本。

2、适配器模式的优缺点

适配器模式的优点:

  1. 可以让原本不兼容的接口协同工作,提高代码的复用性和灵活性。

  2. 可以将适配器类和目标类解耦,使得适配器类和目标类可以独立变化。

  3. 可以增加代码的可读性和可维护性,使代码更加清晰。

适配器模式的缺点:

  1. 可能会增加代码的复杂度和维护成本。

  2. 适配器模式需要增加一个额外的适配器类,增加了代码的量。

  3. 如果设计不当,可能会导致适配器类的滥用,增加代码的混乱程度。

    3、适配器模式的应用场景

适配器模式的应用场景:

  1. 旧接口适配新接口:当系统中的一个类需要使用另一个类的接口,但是这两个类的接口不兼容时,可以使用适配器模式。适配器模式可以将一个类的接口转换成系统需要的另一个接口,从而使得原本不兼容的类可以协同工作。

  2. 多个类的接口统一:当系统中的多个类的接口不统一时,可以使用适配器模式将它们的接口统一成一个接口。这样,这些类就可以协同工作,提高了系统的灵活性和可扩展性。

  3. 适配器模式还可以用于封装有缺陷的接口设计。如果接口的设计不完善,或者需要进行修改,但是又不能对客户端代码产生影响,可以使用适配器模式来封装这些缺陷接口,从而提供一个稳定的接口给客户端使用。

    4、适配器模式的结构

    适配器模式的结构包括以下几个角色:

  1. 目标接口(Target):定义客户端使用的接口,也就是客户端期望的接口。

  2. 源接口(Adaptee):定义需要适配的接口,也就是客户端现有的接口。

  3. 适配器(Adapter):实现目标接口,并持有一个源接口的引用,用于将客户端的请求转换成对源接口的调用。

  4. 客户端(Client):使用目标接口来调用适配器的方法,从而间接调用源接口的方法。

在适配器模式中,客户端通过调用目标接口来使用适配器的方法。适配器持有一个源接口的引用,用于将客户端的请求转换成对源接口的调用,并将返回结果转换成客户端期望的格式。这样,客户端就可以使用适配器来调用源接口的方法,而不需要了解源接口的实现细节。

5、类适配器模式的代码案例

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

假设我们有一个 Adaptee 类,它具有一个 specificRequest() 方法,但是它的接口与我们需要的 Target 接口不兼容。我们需要一个适配器来使得 Adaptee 类能够适配 Target 接口。

首先,我们定义一个 Target 接口:

package com.pany.camp.design.principle.adapter.clazz;

/**
 *
 * @description:  
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 16:57 
 */
public interface Target {
   
   
    void request();
}

然后,我们定义一个 Adaptee 类:

package com.pany.camp.design.principle.adapter.clazz;

/**
 *
 * @description:  Adaptee
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 16:58
 */
public class Adaptee {
   
   

    public void specificRequest() {
   
   
        System.out.println("Adaptee specific request");
    }
}

接下来,我们创建一个适配器类 Adapter ,它继承了 Adaptee 类,并实现了 Target 接口:

package com.pany.camp.design.principle.adapter.clazz;

/**
 *
 * @description:  适配器类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 16:59 
 */
public class Adapter extends Adaptee implements Target {
   
   
    @Override
    public void request() {
   
   
        specificRequest();
    }
}

在适配器类中,我们继承了 Adaptee 类,并实现了 Target 接口。在 request() 方法中,我们调用了 specificRequest() 方法,从而使得 Adaptee 类能够适配 Target 接口。

最后,我们可以使用适配器来调用 Target 接口的方法:

package com.pany.camp.design.principle.adapter.clazz;

/**
 *
 * @description:  客户端
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:00
 */
public class Client {
   
   
    public static void main(String[] args) {
   
   
        Target target = new Adapter();
        target.request();
    }
}

输出结果如下:

Adaptee specific request

Process finished with exit code 0

在客户端代码中,我们创建了一个适配器对象,并将其赋值给 Target 接口的引用。然后,我们调用了 request() 方法,实际上是调用了适配器的 request() 方法,从而间接调用了 Adaptee 类的 specificRequest() 方法。

6、对象适配器模式的代码案例

以下是一个使用对象适配器模式的示例代码:

假设我们有一个 Adaptee 类,它具有一个 specificRequest() 方法,但是它的接口与我们需要的 Target 接口不兼容。我们需要一个适配器来使得 Adaptee 类能够适配 Target 接口。

首先,我们定义一个 Target 接口:

package com.pany.camp.design.principle.adapter.object;

/**
 *
 * @description:  Target
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:03
 */
public interface Target {
   
   
    void request();
}

然后,我们定义一个 Adaptee 类:

package com.pany.camp.design.principle.adapter.object;

/**
 *
 * @description:  Adaptee
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:04
 */
public class Adaptee {
   
   

    public void specificRequest() {
   
   
        System.out.println("Adaptee specific request");
    }
}

接下来,我们创建一个适配器类 Adapter ,它实现了 Target 接口,并持有一个 Adaptee 对象的引用:

package com.pany.camp.design.principle.adapter.object;

/**
 *
 * @description:  适配器类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:04
 */
public class Adapter implements Target {
   
   
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
   
   
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
   
   
        adaptee.specificRequest();
    }
}

在适配器类中,我们实现了 Target 接口,并持有一个 Adaptee 对象的引用。在 request() 方法中,我们调用了 Adaptee 对象的 specificRequest() 方法,从而使得 Adaptee 类能够适配 Target 接口。

最后,我们可以使用适配器来调用 Target 接口的方法:

package com.pany.camp.design.principle.adapter.object;

/**
 *
 * @description:  客户端类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:05
 */
public class Client {
   
   

    public static void main(String[] args) {
   
   
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}

在客户端代码中,我们创建了一个 Adaptee 对象和一个适配器对象,并将适配器对象赋值给 Target 接口的引用。然后,我们调用了 request() 方法,实际上是调用了适配器的 request() 方法,从而间接调用了 Adaptee 类的 specificRequest() 方法。

7、接口适配器模式的代码案例

以下是一个简单的接口适配器模式的代码案例,使用Java语言实现:

  1. 定义目标接口
package com.pany.camp.design.principle.adapter.interfaces;

/**
 *
 * @description:  Target
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:16
 */
public interface Target {
   
   
    void request();
}
  1. 实现目标接口的具体类
package com.pany.camp.design.principle.adapter.interfaces;

/**
 *
 * @description:  具体类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:16
 */
public class ConcreteTarget implements Target {
   
   
    @Override
    public void request() {
   
   
        System.out.println("ConcreteTarget.request() is called");
    }
}
  1. 定义适配器接口
package com.pany.camp.design.principle.adapter.interfaces;

/**
 *
 * @description:  适配器接口
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:17
 */
public interface Adapter {
   
   
    void specificRequest();
}
  1. 实现适配器接口的具体类,同时持有目标接口的引用
package com.pany.camp.design.principle.adapter.interfaces;

/**
 *
 * @description:  适配器接口的具体类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:17
 */
public class ConcreteAdapter implements Adapter {
   
   

    private Target target;

    public ConcreteAdapter(Target target) {
   
   
        this.target = target;
    }

    @Override
    public void specificRequest() {
   
   
        System.out.println("ConcreteAdapter.specificRequest() is called");
        target.request();
    }
}
  1. 在客户端中使用适配器
package com.pany.camp.design.principle.adapter.interfaces;

/**
 *
 * @description:  客户端
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 17:20
 */
public class Client {
   
   
    public static void main(String[] args) {
   
   
        Target target = new ConcreteTarget();
        Adapter adapter = new ConcreteAdapter(target);
        adapter.specificRequest();
    }
}

在上面的代码中, ConcreteTarget 是目标接口的具体实现类, ConcreteAdapter 是适配器接口的具体实现类,并且持有一个目标接口的引用。在客户端中,我们创建了一个目标接口的实例和一个适配器接口的实例,然后通过适配器接口调用目标接口的方法。

1686494501743.jpg

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

目录
相关文章
|
1月前
|
设计模式 Java API
重构旧代码的秘诀:用设计模式 - 适配器模式(Adapter)给Java项目带来新生
【4月更文挑战第7天】适配器模式是解决接口不兼容问题的结构型设计模式,通过引入适配器类实现目标接口并持有不兼容类引用,实现旧代码与新接口的协作。适用于处理兼容性问题、整合遗留代码和集成第三方库。应用时,识别不兼容接口,创建适配器类转换方法调用,然后替换原有引用。注意保持适配器简单、使用组合和考虑扩展性。过度使用可能导致系统复杂和维护成本增加,应谨慎使用。
|
1月前
|
设计模式 Java 中间件
23种设计模式,适配器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要目标是让原本由于接口不匹配而不能一起工作的类可以一起工作。适配器模式主要有两种形式:类适配器和对象适配器。类适配器模式通过继承来实现适配,而对象适配器模式则通过组合来实现
50 4
|
24天前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
|
7天前
|
设计模式 Java C#
【设计模式】第六篇:来康康适配器模式
类适配器模式 主要使用继承实现,耦合度高,且在单继承的语言中使用会受限,还需要防止继承带来的一些问题
13 5
|
8天前
|
设计模式 算法 关系型数据库
设计模式第七讲-外观模式、适配器模式、模板方法模式详解
系统要求所有的数据库帮助类必须实现ISqlHelp接口,面向该接口编程,如SQLServerHelp类。 此时第三方提供了一个新的MySql的帮助类(假设是dll,不能修改),它的编程规范和ISqlHelp不兼容,这个时候就需要引入适配器类,使二者能相互兼容。
140 0
|
1月前
|
设计模式 Java Go
【设计模式】适配器模式怎么理解?
【设计模式】适配器模式怎么理解?
18 1
|
1月前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式
[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式
|
1月前
|
设计模式 Go
[设计模式 Go实现] 结构型~适配器模式
[设计模式 Go实现] 结构型~适配器模式
|
1月前
|
设计模式 Java
【设计模式系列笔记】适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一种接口。它允许原本由于接口不匹配而无法一起工作的类能够协同工作。适配器模式通常涉及一个称为适配器的类,它充当两个不兼容接口之间的桥梁。
45 6
|
1月前
|
设计模式 Java 数据库
小谈设计模式(18)—适配器模式
小谈设计模式(18)—适配器模式