博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌
Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕
文章目录
- 1、什么是适配器模式
- 2、适配器模式的优缺点
- 3、适配器模式的应用场景
- 4、适配器模式的结构
- 5、类适配器模式的代码案例
- 6、对象适配器模式的代码案例
- 7、接口适配器模式的代码案例
1、什么是适配器模式
适配器模式是一种结构型设计模式,它用于将一个类的接口转换成客户端所期望的另一个接口。适配器模式可以让原本由于接口不兼容而无法一起工作的类能够协同工作。
适配器模式的主要作用是解决两个已有接口之间的不兼容问题,以便它们能够协同工作。适配器模式有三种实现方式:类适配器、对象适配器和接口适配器。
类适配器是通过继承来实现的,它可以适配一个类的接口到另一个类的接口。对象适配器是通过组合来实现的,它可以适配一个对象的接口到另一个对象的接口。接口适配器是通过抽象类来实现的,它可以适配一个接口的部分方法到另一个接口。
适配器模式的优点是可以让原本不兼容的接口协同工作,提高代码的复用性和灵活性。缺点是可能会增加代码的复杂度和维护成本。
2、适配器模式的优缺点
适配器模式的优点:
-
可以让原本不兼容的接口协同工作,提高代码的复用性和灵活性。
-
可以将适配器类和目标类解耦,使得适配器类和目标类可以独立变化。
-
可以增加代码的可读性和可维护性,使代码更加清晰。
适配器模式的缺点:
-
可能会增加代码的复杂度和维护成本。
-
适配器模式需要增加一个额外的适配器类,增加了代码的量。
-
如果设计不当,可能会导致适配器类的滥用,增加代码的混乱程度。
3、适配器模式的应用场景
适配器模式的应用场景:
-
旧接口适配新接口:当系统中的一个类需要使用另一个类的接口,但是这两个类的接口不兼容时,可以使用适配器模式。适配器模式可以将一个类的接口转换成系统需要的另一个接口,从而使得原本不兼容的类可以协同工作。
-
多个类的接口统一:当系统中的多个类的接口不统一时,可以使用适配器模式将它们的接口统一成一个接口。这样,这些类就可以协同工作,提高了系统的灵活性和可扩展性。
-
适配器模式还可以用于封装有缺陷的接口设计。如果接口的设计不完善,或者需要进行修改,但是又不能对客户端代码产生影响,可以使用适配器模式来封装这些缺陷接口,从而提供一个稳定的接口给客户端使用。
4、适配器模式的结构
适配器模式的结构包括以下几个角色:
-
目标接口(Target):定义客户端使用的接口,也就是客户端期望的接口。
-
源接口(Adaptee):定义需要适配的接口,也就是客户端现有的接口。
-
适配器(Adapter):实现目标接口,并持有一个源接口的引用,用于将客户端的请求转换成对源接口的调用。
-
客户端(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语言实现:
- 定义目标接口
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();
}
- 实现目标接口的具体类
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");
}
}
- 定义适配器接口
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();
}
- 实现适配器接口的具体类,同时持有目标接口的引用
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();
}
}
- 在客户端中使用适配器
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 是适配器接口的具体实现类,并且持有一个目标接口的引用。在客户端中,我们创建了一个目标接口的实例和一个适配器接口的实例,然后通过适配器接口调用目标接口的方法。
💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊