前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >​# 连接多元世界的纽带——适配器模式的魅力

​# 连接多元世界的纽带——适配器模式的魅力

原创
作者头像
码匠er
发布2024-03-02 21:57:59
1030
发布2024-03-02 21:57:59
举报
文章被收录于专栏:设计模式设计模式

📚 A公司正在开发一个电子商务平台,团队决定集成一个新的服务。例如支付宝、微信等第三方的支付选项给用户,然而,我们的服务之前的支付接口和它们的接口是不兼容的,导致无法直接继承,需要修改之前的代码,比较麻烦,我们想在不改变现有支付系统的前提下,将支付宝的支付系统集成在我们的平台中。

🙋‍♂️ 适配器模式就可以解决以上问题,通过创建一个适配器,我们可以使不兼容的系统相互调用。

在本篇文章中,我们就开始学习适配器模式吧~

1. 概述

适配器模式是通过引入一个叫做适配器的包装类,将一个接口转换为客户希望的另一个接口(适配者),使这两个不兼容的接口可以在一个系统中工作。

🏷️ 适配器模式有两种表现形式,分别为类适配器模和对象适配器模式。

对象适配器:适配器和适配者之间是关联关系; 类适配器:适配器和适配者之间是继承或者实现关系;

❗ 简单理解适配器模式

Java中的Arrays有个排序(sort)方法,只能对数组进行排序,但是如果我们想要对List排序,就需要引入一个适配器,对List做处理,调用Arrays中的排序方法实现这个功能。你懂了吗?😉

2. 结构

适配器模式由以下角色组成:

  • 目标抽象类(Target):目标抽象类就是客户端直接调用的接口,可以是一个抽象类或接口,也可以是一个具体的类;
  • 适配器类(Adapter):适配器类可以调用另一个接口,对目标抽象类适配者类适配,使二者产生联系,是适配器模式的核心;
  • 适配者类(Adaptee):适配者类就是被适配的类,它是一个已经存在的接口,一般是一个具体的类,是客户端希望调用的方法;

3. UML图

  • 对象适配器
  • 类适配器

4. 实现

  • 对象适配器
代码语言:java
复制
// 目标抽象类
class abstract Target {
	public abstract void method();
}
代码语言:java
复制
// 适配者类
class Apaptee {
	public void othermethod() {
		// 具体的实现逻辑
	}
}
代码语言:java
复制
// 适配器类
class Adapter extends Target {
	private Adaptee adaptee; // 适配器中关联适配者
	
	public Adapter(Adaptee adaptee) {
		this.adaptee = adaptee;
	}
	
    // 适配器中可以直接调用适配者的具体方法
	public void methed() {
		adaptee.othermethod()
	}
}
  • 类适配器
代码语言:java
复制
// 由于java是单继承,所以目标抽象类不能是抽象类,只能是接口
interface Target {
	void method();
}
代码语言:java
复制
// 适配者类
class Apaptee {
	public void othermethod() {
		// 具体的实现逻辑
	}
}
代码语言:java
复制
// 适配器类
class Adapter extends Adaptee implements Target {
	public void methed() {
		othermethod() // 由于继承了Adaptee类,可以直接使用othermethod方法
	}
}

5. 案例分析

我们实现上述的A公司想要新增支付宝支付的功能实例代码。

0️⃣ 公司之前的支付接口代码

代码语言:java
复制
public interface PayService {
    void pay();
}

1️⃣ 支付宝支付接口代码

代码语言:java
复制
public class AlipayService {
    void alipay() {
        System.out.println("支付宝支付");
    }
}

2️⃣ 引入适配者类的代码

代码语言:java
复制
public class AlipayServiceAdapter implements PayService{

    private AlipayService alipayService;

    public AlipayServiceAdapter(AlipayService alipayService) {
        this.alipayService = alipayService;
    }

    @Override
    public void pay() {
        alipayService.alipay();
    }
}

3️⃣ 客户端调用代码

代码语言:java
复制
public class Client {
    public static void main(String[] args) {
        AlipayService alipayService = new AlipayService();
        PayService payService = new AlipayServiceAdapter(alipayService);
        payService.pay();
    }
}

✍ 上述代码使用了对象适配器模式,大家可以使用类适配器模式实现相同功能哦~

6. 优缺点

✅️ 优点:

  • 目标类和适配类解耦。引入适配器类重用现有的类就可以新增新的功能接口,无需修改原来的结构;
  • 单一职责。将接口或者数据的转换代码从系统的主要业务分离出来;

❌ 缺点:

  • 类适配器模式使用限制。由于Java语言不支持多继承,一次只能适配一个适配者类,不能适配多个;
  • 增加代码负责度。因为需要新增接口和类,比直接修改已有代码更复杂;

7. 使用场景

  • 系统需要使用现有类,而这些类和工程现有代码不兼容;
  • 复用一些类,它们处于同一继承体系,并且它们又有一些公共方法。

8. 扩展

8.1 双向适配器模式

双向适配器模式是适配器模式的一种变体,它允许两个不兼容的接口之间进行双向适配,就是适配器类中,支持对目标类和适配者的引用,这个适配器就是双向适配器

📚 B公司需要开发一个通信接口,它们之间需要使用双向适配器模式,下面是实现的代码。

代码语言:java
复制
public interface ServiceInterface {
    void sendMsgToClient(String msg);
}

public interface ClientInterface {
    void sendMsgToService(String msg);
}

public class Service implements ServiceInterface{

    @Override
    public void sendMsgToClient(String msg) {
        System.out.println("Service 接受到消息:" + msg);
    }
}

public class Client implements ServiceInterface{

    @Override
    public void sendMsgToClient(String msg) {
        System.out.println("Client 接收到消息:" + msg);
    }
}
代码语言:java
复制
public class BidirectionalAdapter implements ServiceInterface, ClientInterface{
    private Service service;
    private Client client;

    public BidirectionalAdapter(Service service, Client client) {
        this.service = service;
        this.client = client;
    }

    @Override
    public void sendMsgToService(String msg) {
        service.sendMsgToClient(msg);
    }

    @Override
    public void sendMsgToClient(String msg) {
        client.sendMsgToClient(msg);
    }
}
代码语言:java
复制
public class Main {

    public static void main(String[] args) {
        Service service = new Service();
        Client client = new Client();

        BidirectionalAdapter adapter = new BidirectionalAdapter(service, client);
        adapter.sendMsgToClient("service 的消息");

        adapter.sendMsgToService("client 的消息");
    }
}

🪐 运行结果:

8.2 缺省适配器模式

缺省适配器模式也是适配器模式的一种变体,其应用比较广泛。当不需要实现一个接口提供的所有方法时,可先设计一个抽象类实现该接口,并为每一个方法提供一个空方法来覆盖父类的方法,那么抽象类的子类可以自己选择覆盖父类的方法实现需求。

缺省适配器模式适用于不想使用接口中的所有方法的情况。

缺省适配器模式中,包含3个角色:

  • 适配者接口(ServiceInterface):是一个接口,定义了大量的方法;
  • 缺省适配器(DefaultAdapter):缺省适配器的核心,使用空方法的实现了在适配者接口中声明的方法,通常为抽象类;
  • 具体业务(ConcreteService):是缺省适配器类的子类,如果直接实现适配者接口,需要实现所有的方法,如果继承了缺省适配器,则只需要适配想要使用的方法;

📚 C公司需要开发一个界面显示的功能,定义了一个接口ViewService,里面定义了很多的方法,现在需要实现在某平台的显示功能,只需要实现其中的一部分方法,如果我们直接继承了ViewService,则需要实现所有的方法,其他方法为空方法,现在我们可以引入一个缺省适配器类ViewAdapter类,在后续增加功能时,只需要继承ViewAdapter类即可。请看下面代码

代码语言:java
复制
public interface ViewService {
    void showBanner();

    void showColor();

    void showButton();

    void showCmd();

    void showStyles();

    void showShape();
}
代码语言:java
复制
public abstract class ViewAdapter implements ViewService{
    @Override
    public void showBanner() {

    }

    @Override
    public void showColor() {

    }

    @Override
    public void showButton() {

    }

    @Override
    public void showCmd() {

    }

    @Override
    public void showStyles() {

    }

    @Override
    public void showShape() {

    }
}
代码语言:java
复制
public class LinuxViewService extends ViewAdapter{
    // 只需要实现需要使用的方法
    @Override
    public void showCmd() {
        System.out.println("展示cmd框");
    }
}

9. 总结

好了,我们这篇文章到此就要告一段落了,通过这篇文章,我们学会使用了适配器模式,以后如果在项目中遇到接口不兼容的问题,就要先考虑一下适配器模式,相信我们会写出更好的代码~

我会持续更新关于技术的文章❤️🤎💚🧡💛

欢迎大家点赞👍 收藏 ⭐ 关注 💡三连支持一下~~~

查看文章过程中有问题或者有需要修改的地方,欢迎私聊我哦 🗨🗨🗨

不管世界变成什么样,我们都要加强自己自身能力~✊✊✊

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概述
  • 2. 结构
  • 3. UML图
  • 4. 实现
  • 5. 案例分析
  • 6. 优缺点
  • 7. 使用场景
  • 8. 扩展
    • 8.1 双向适配器模式
      • 8.2 缺省适配器模式
      • 9. 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档