首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式实战-适配器模式,承上启下

设计模式实战-适配器模式,承上启下

作者头像
架构师修炼
发布2020-07-20 11:19:30
4340
发布2020-07-20 11:19:30
举报

这节,我们来看下另外一种设计模式,属于结构型模式——适配器模式。

1、定义

适配器,其实很好理解,生活中也随处可见,比如电源适配器、usb 适配器等等,那么适配器模式,也被称为Wrapper 模式。

Wrapper 有“包装器”的意思,适配器模式的定义是:将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,解决的痛点便是因接口不兼容导致的类不能正常工作的问题。

如上图所示,A、B 代表已经塑模成型的物体 A 和 B,如果想将这两种物体安装在一起,因为两者的接口是不兼容的,不可能直接安装在一起,这个时候该怎么办?这里,我们可以引入物体 C,物体 C 既要适配 A 的接口,又要适配 B 的接口,经过 C 的无缝“衔接”,便将 A、B 完美结合在了一起。

这里的物体 C 就是我们要说的适配器角色,起到了一定的角色转换的作用。再举个例子,如果想让直流 12v 的笔记本电脑工作在交流 220v 的电源下,就必须要一个电源适配器,该适配器的作用就是将 220v 的 AC 交流转为 12v 的 DC 直流,这就是适配器该干的工作,弥补两者之间的空白——承上启下。

什么时候使用适配器模式,从上面的案例我们也可以看出一点端倪:

  • 现有的类或接口不能满足需求,且一般无法直接修改现有类或接口。比方该类为三方提供,就无法修改,亦或者像A、B 这种已经塑模成型的物件,可能已大规模在使用中,所以不允许修改。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。

2、组成角色

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

适配器模式的通用类图如下:

适配器模式包含的角色如下:

  • 目标角色(Target):该角色定义把其它类转换为何种接口,也就是我们的期望接口,可以是一个抽象类或接口,也可以是具体类。以上文中笔记本电脑为例,即指让笔记本正常工作的直流 12v 电源;
  • 适配器角色(Adapter):适配器可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,适配器类是适配器模式的核心,通常都是一个具体的类。以上文中笔记本电脑为例,即指电源适配器;
  • 源角色(被适配 Adaptee ):你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。以上文中笔记本电脑为例,即指 220v 的 AC 电源;
  • 请求者(Client):该角色负责使用 Target 定义的方法进行具体处理,以上文中笔记本电脑为例,即指使用 12v 电源驱动的笔记本电脑。

总的一句话,Adapter 就是一个在 Client 中使用 Target 定义的接口来使用 Adaptee 角色(调用 Adaptee 中的方法)的存在。

3、类适配器(使用继承)

如上图为使用类适配器实现的适配器模式,具体代码如下:

首先是 Target 接口,也就是我们要适配的目标接口:

package com.isoft;

public interface Target {

    public abstract void targetMethod1();

    public abstract void targetMethod2();
}

接下来是要被适配的“接口”,即 Adaptee:

package com.isoft;

public class Adaptee {

    public void methodA() {
        System.out.println("Adaptee methodA invoked.");
    }

    public void methodB() {
        System.out.println("Adaptee methodB invoked.");
    }

}

然后是我们的适配器,关键代码如下:

package com.isoft;

public class Adapter extends Adaptee implements Target{

    @Override
    public void targetMethod1() {
        System.out.println("Adapter targetMethod1 inkoked.");
        methodA();
    }

    @Override
    public void targetMethod2() {
        System.out.println("Adapter targetMethod2 inkoked.");
        methodB();
    }
}

最后是我们的 Client,在这里就是 Main 类:

package com.isoft;

public class Main {

    public static void main(String[] args) {

        // 通过Adapter继承Adaptee实现了Adaptee角色的调用
        Target target = new Adapter();
        target.targetMethod1();
        target.targetMethod2();

    }
}

执行结果如下:

Adapter targetMethod1 inkoked.
Adaptee methodA invoked.
Adapter targetMethod2 inkoked.
Adaptee methodB invoked.

这里,Client 使用者并不知道 Adaper 适配器是如何工作的,就好比笔记本电脑只需要在 12v 电压下正常工作即可,具体适配器如何适配实现电压转换,笔记本电脑无需关心。

4、对象适配器(使用委托)

如上图为使用对象适配器实现的适配器模式,具体代码如下:

首先是我们要适配的目标类,这里不是接口了注意:

package com.isoft;

public abstract class Target {

    public abstract void targetMethod1();

    public abstract void targetMethod2();

}

因为 java 的类不支持多继承,但是在单继承模式下我们可以使用委托来实现方法的调用,修改后的 Adapter 适配器代码如下:

package com.isoft;

public class Adapter extends Target{

    private Adaptee adaptee;

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

    @Override
    public void targetMethod1() {
        System.out.println("Adapter targetMethod1 inkoked.");
        adaptee.methodA();
    }

    @Override
    public void targetMethod2() {
        System.out.println("Adapter targetMethod2 inkoked.");
        adaptee.methodB();
    }
}

Client 调用的时候没有变化,还是如下:

public static void main(String[] args) {

    // 通过Adapter使用委托,实现了Adaptee角色的调用
    Target target = new Adapter();
    target.targetMethod1();
    target.targetMethod2();

}

输出结果:

Adapter targetMethod1 inkoked.
Adaptee methodA invoked.
Adapter targetMethod2 inkoked.
Adaptee methodB invoked.

5、优缺点

主要优点:

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构;
  • 增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用;
  • 可以将两个互不相干的类关联在一起;
  • 增强系统灵活性。

主要缺点:

  • 类适配器对于 Java、C# 等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。

6、应用场景

类适配器与对象适配器的使用场景一致,主要应用于如下场景:

  • 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码,这时创建一个适配器就能间接去改造这个类中的方法;
  • 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

7、总结

适配器模式,本身属于一种结构型模式,用于在两个对象或者系统之间建立适配链接,使得前后系统衔接更加平滑,适配器模式的实现主要有继承方式的类适配器,和委托方式的对象适配器。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师修炼 微信公众号,前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、定义
  • 2、组成角色
  • 3、类适配器(使用继承)
  • 4、对象适配器(使用委托)
  • 5、优缺点
  • 6、应用场景
  • 7、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档