阅读原文请访问我的博客BrightLoong's Blog
一. 概述
适配器模式(Adapter)
,将一个类的接口转换为客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那个类可以一起工作。
关于适配器,现实生活中也有很多例子,比如电源适配器,中国家庭供电为220V,而手机一般需求是在5V,这里220V就是不兼容的那个类,但我们又需要其供电,我们用电源适配器将其转为5V,使手机能正常充电。还有各种转接头(HDMI转接头,type-c转接头等),顺便说一下,Java中的IO中可以看到适配器模式的使用。
适配器模式属于结构型模式
二. UML类图解析
在GoF的设计模式中,适配器模式讲了两种类型——类适配器模式和对象适配器模式。由于类适配器模式需要继承被适配的类,同时有可能需要继承目标类,而Java又不支持多重继承,所以平时常用的是对象适配器模式。下面也会对类适配器模式进行简单的介绍。
对象适配器模式
- Client:客户端。
- Target:目标接口,客户端所期待的目标接口(可以是具体的或抽象的类,也可以是接口)。
- Adapter:适配器,实现目标接口,通过在内部持有一个Adaptee引用,把源接口(Adaptee)转成目标接口(Target)。
- Adaptee:需要适配的类。
类适配器模式
基本和对象适配器模式相同,唯一不同的是适配器(Adapter)不在持有Adaptee的引用,而采用继承Adaptee的方式,实现把源接口(Adaptee)转成目标接口(Target)。
三. 代码实现
就基于上面的电源适配器场景来进行代码实现。目标接口——MobileCharge(需要5V电流),需要被适配的22V电源——Power220V,电源适配器——PowerAdapter
目标接口——MobileCharge
package io.github.brightloong.design.adapter;
/**
* 充电接口
* Created by BrightLoong on 2018/6/6.
*/
public interface MobileCharge {
public void outPut5V();
}
需要被适配的22V电源——Power220V
package io.github.brightloong.design.adapter;
/**
* 需要被适配的类
* Created by BrightLoong on 2018/6/6.
*/
public class Power220V {
public void outPut220V() {
System.out.println("输出220V电流");
}
}
电源适配器——PowerAdapter(对象适配器模式)
package io.github.brightloong.design.adapter;
/**
* 对象适配器
* Created by BrightLoong on 2018/6/6.
*/
public class PowerAdapter implements MobileCharge {
//需要适配的220V电源
private Power220V power220V;
public PowerAdapter(Power220V power220V) {
this.power220V = power220V;
}
public void outPut5V() {
power220V.outPut220V();
System.out.println("电源适配器转换");
System.out.println("输出5V电流");
}
}
使用类适配模式的电源适配器——PowerAdapter2
package io.github.brightloong.design.adapter;
/**
* 类适配器,使用继承的方式
* Created by BrightLoong on 2018/6/6.
*/
public class PowerAdapter2 extends Power220V implements MobileCharge {
public void outPut5V() {
super.outPut220V();
System.out.println("电源适配器转换");
System.out.println("输出5V电流");
}
}
客户端调用和输出
package io.github.brightloong.design.adapter;
/**
* Created by BrightLoong on 2018/6/6.
*/
public class Client {
public static void main(String[] args) {
MobileCharge mobileCharge = new PowerAdapter(new Power220V());
System.out.println("手机充电");
mobileCharge.outPut5V();
System.out.println("-------------------");
//类适配器模式
MobileCharge mobileCharge2 = new PowerAdapter2();
mobileCharge2.outPut5V();
}
}
输出结果:
手机充电
输出220V电流
电源适配器转换
输出5V电流
-------------------
输出220V电流
电源适配器转换
输出5V电流
四. 总结
使用场景
注意:适配器模式是更多的为了解决已有的在运行的项目中的问题,而不是解决开发阶段的项目,开发阶段的项目应该进行良好的设计。
- 系统的数据和行为都正确,但接口不符时。
- 希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
- 想使用一个已经存在的类,但是它的接口,也就是它的方法和你的要求不同时。
优点
- 因为适配器模式可以让不满足要求的类满足要求,所以提高了类的复用。
- 使目标类和适配者类解耦,增加了类的透明性,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。
- 具有较强的灵活性和扩展性,可以很方便的增加适配器。
缺点
- 一次最多只能适配一个适配者类,不能同时适配多个适配者。 (类适配器存在的问题,因为不能多重继承,考虑使用对象适配器,持有多个适配者)
- 目标抽象类只能为接口,不能为类,其使用有一定的局限性。(类适配器存在的问题,因为不能多重继承,如果是类,考虑继承而不是实现)
- 对象适配器