# 适配器模式Adapter
阅读量  loading 
 # 一、概念
# 1、定义
将一个类的接口(被适配者)转换成客户期望的另一个结构(目标类),使原本不兼容的类可以一起工作
# 2、类型
结构型
# 3、适用场景
- 已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)
 - 不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案
 
# 4、优点
- 能提高类的透明性和复用,现有的类复用但不需要改变
 - 目标类和适配器类解耦,提高程序扩展性
 - 符合开闭原则
 
# 5、缺点
- 适配器编写过程需要全面考虑,可能会增加系统的复杂性
 - 增加系统代码可读的难度
 
# 6、扩展
# 类适配器
通过类继承实现的
# 对象适配器
符合组合复用原则,并且使用委托机制,通过组合实现
# 7、相关设计模式
- 适配器模式和外观模式
 
都是对现有的类进行封装。适配器模式复用原有的接口,使两个已有的接口协同工作;而外观模式定义了新的接口,在现有的系统中提供一个更方便的访问入口。
# 二、Coding
先介绍一下适配器模式中被适配者的角色:
public class Adaptee {
    public void adapteeRequest() {
        System.out.println("被适配者的方法");
    }
}
 1
2
3
4
5
6
2
3
4
5
6
目标类,也就是适配后,最终我们想要的类:
public interface Target {
    void request();
}
 1
2
3
4
2
3
4
这里定义为了一个接口。
目标类的具体实现类:
public class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("ConcreteTarget目标方法");
    }
}
 1
2
3
4
5
6
7
2
3
4
5
6
7
接下来就是最终要的适配器类了。
# 类适配器
类适配器中的适配器类是通过继承被适配类实现的:
public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        super.adapteeRequest();
    }
}
 1
2
3
4
5
6
7
2
3
4
5
6
7
通过继承被适配者,然后实现目标接口,在目标接口的方法中调用了被适配者的方法,这样就将被适配者的方法适配到了目标方法。实际上在调用父类的的 adapteeRequest() 方法前后还可以做一系列操作来实现代码增强。
应用层:
    public static void main(String[] args) {
        Target target = new ConcreteTarget();
        target.request();
        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
 1
2
3
4
5
6
7
2
3
4
5
6
7
target 是原始的 Target 的实现类,后面通过适配器实现了 Target 接口,实际在适配器内部调用的是被适配者的方法,从而完成了适配。
运行结果:
ConcreteTarget目标方法
被适配者的方法
 1
2
2
# 对象适配器
对象适配器的适配器类是通过组合被适配器实现的:
public class Adapter implements Target {
    private Adaptee adaptee = new Adaptee();
    @Override
    public void request() {
        adaptee.adapteeRequest();
    }
}
 1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
也同样完成了适配功能。同样的在适配过程前后可以增加自己的逻辑代码。
应用层不用变化,直接可以复用:
    public static void main(String[] args) {
        Target target = new ConcreteTarget();
        target.request();
        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
 1
2
3
4
5
6
7
2
3
4
5
6
7
运行结果:
ConcreteTarget目标方法
被适配者的方法
 1
2
2
一样的效果。
# 应用
最能体现适配器模式的就是充电器的适配电源了,将220V交流电(被适配者)通过手机充电器(适配器)转换为手机充电电压(目标)。先看下被适配者类,也就是220V交流电:
public class AC220 {
    public int outputAC220V() {
        int output = 220;
        System.out.println("输出交流电" + output + "V");
        return output;
    }
}
 1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
接下来是目标类,5v直流电:
public interface DC5 {
    int outputDC5V();
}
 1
2
3
4
2
3
4
最终要的角色,手机充电器,也就是适配器:
public class PowerAdapter implements DC5 {
    private AC220 ac220 = new AC220();
    @Override
    public int outputDC5V() {
        int adapterInput = ac220.outputAC220V();
        // 变压器
        int adapterOutput = adapterInput / 44;
        System.out.println("使用PowerAdapter输入AC:" + adapterInput + "V,输出DC:" + adapterOutput);
        return adapterOutput;
    }
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
这里通过组合的方式,在 outputDC5V() 方法中调用了被适配者的 outputAC220V() 方法,并做了逻辑处理,完成了适配。
看下应用层:
    public static void main(String[] args) {
        DC5 dc5 = new PowerAdapter();
        dc5.outputDC5V();
    }
 1
2
3
4
2
3
4
运行结果:
输出交流电220V
使用PowerAdapter输入AC:220V,输出DC:5
 1
2
2
是不是很简单。