适配器模式,顾名思义,它的职责就是做适配,将两个不兼容的东西,通过适配器的连接,变得兼容起来。有些情况下,需要兼容的二者并不能修改,所以需要“适配器”这个中间件做一个桥接。
一、定义
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
UML:
Target:目标角色,也就是期待得到的接口,可以不是类,比如可以使方法
Adaptee:需要适配的接口
Adapter:适配器
二、使用场景
1、系统需要现有的类,而此类的接口不兼系统
2、想要建立起一个可以重复使用的类,用于与一些彼此之间没有太大联系的一些类。
3、需要一个统一的输出接口,而输出端不可预知。
适配器模式分为三种:对象适配器、类适配器、接口适配器,接下来一一讲解。
三、示例
3.1 对象适配器:
使用代理关系把被适配的类的API转换成目标类的API
先说一下场景:我有一台苹果手机,充电的接口是Lighting接口,手机没电了现在需要充电,但是我的数据线坏了,只能管同事借,但是同事用的是安卓手机,充电的接口是OTG接口,我的苹果手机也插不上。。。这怎么办呢,听说X宝有卖转接头的??那么这个“转接头”,就是一个适配器,他会帮我把安卓的OTG接口转换成Lighting接口,然后我就可以插上给我的苹果手机充电了!
不多说,直接上代码:
首先是安卓的OTG接口:
/**
* 安卓充电口
*/
public interface OTG {
void thisIsOTG();
}
然后是苹果的Lighting接口:
/**
* 苹果充电口
*/
public interface Lighting {
void thisIsLighting();
}
/**
* 苹果充电口实现类
*/
public class LightingImpl implements Lighting {
@Override
public void thisIsLighting() {
System.out.println("苹果的Lighting充电口,扁扁的上下一样宽");
}
}
现在我要充电了,需要一个转接头:
/**
* 适配器
*/
public class Adapter implements OTG {
private Lighting mLighting;
public Adapter(Lighting lighting) {
this.mLighting = lighting;
}
@Override
public void thisIsOTG() {
mLighting.thisIsLighting();
}
}
转接头有了,那么现在开始转换,充电:
public static void main(String[] args) {
//将手里的安卓OTG接口用适配器Adapter转化为苹果的Lighting接口
OTG otg = new Adapter(new LightingImpl());
otg.thisIsOTG();
}
看一下输出的log:
12-20 11:34:43.630 8835-8835/lbx.myapplication I/System.out: 苹果的Lighting充电口,扁扁的上下一样宽
好了,现在我可以愉快的充电了!
3.2 类适配器:
场景还是同样的场景,目的还是同样的目的,不同的是适配器Adapter的写法,为了方便,我把代码全部贴出来一遍:
首先还是,两个不同手机的接口:
/**
* 安卓充电口
*/
public interface OTG {
void thisIsOTG();
}
/**
* 苹果充电口
*/
public interface Lighting {
void thisIsLighting();
}
然后实现接口:
/**
* 安卓充电口实现类
*/
public class OTGImpl implements OTG {
@Override
public void thisIsOTG() {
System.out.println("安卓的OTG充电口,扁扁的上宽下窄");
}
}
接下来就是最主要的适配器了:
/**
* 适配器
*/
public class Adapter extends OTGImpl implements Lighting {
@Override
public void thisIsLighting() {
System.out.println("苹果的Lighting充电口,扁扁的上下一样宽");
}
}
接下来开始转换、充电:
public static void main(String[] args) {
//将手里的安卓OTG接口用适配器Adapter转化为苹果的Lighting接口
OTG otg = new Adapter();
otg.thisIsLighting();
}
让我们看下log:
12-20 14:10:00.820 2085-2085/lbx.myapplication I/System.out: 苹果的Lighting充电口,扁扁的上下一样宽
怎么样,也实现了要达到的效果!
3.3 接口适配器
接口适配相对容易一下,比如一个接口里面有好多个方法,当我们用子类去实现这个类的时候并不是所有的方法都要用到,如果直接实现这个接口,所有的方法都跟着实现,代码非常的臃肿,而我们的期望是我们只实现一些我们用得到的方法。
举个栗子:
场景说明:模拟一个下载功能,当开始下载的时候,输出log:开始下载,下载成功后,输出log:下载成功。
然后假设有一个第三方下载的框架,当然框架是我们不可修改的,以为内是别人的代码:
public class DownLoadHelper {
/**
* 模拟下载
*/
public void download(DownLoadListener downLoadListener) {
downLoadListener.onStart();
downLoadListener.onLoading();
downLoadListener.onSuccess();
downLoadListener.onFinish();
}
}
public interface DownLoadListener {
/**
* 开始下载
*/
void onStart();
/**
* 开始中
*/
void onLoading();
/**
* 开始成功
*/
void onSuccess();
/**
* 开始完成
*/
void onFinish();
}
当我们拿到这个框架,开始做我们的工作,肯定会这么写:
public static void main(String[] args) {
DownLoadHelper downLoadHelper = new DownLoadHelper();
downLoadHelper.download(new DownLoadListener() {
@Override
public void onStart() {
System.out.println("开始下载");
}
@Override
public void onLoading() {
}
@Override
public void onSuccess() {
System.out.println("下载成功");
}
@Override
public void onFinish() {
}
});
}
然后我们发现,只用到了onStart和onSuccess,剩下的两个回调并没有用到,完全没用,代码臃肿,占地方,反正强迫症的我是受不了,这仅仅是多出了两个方法,假设多出了20个方法呢?只用到两个,太不值了吧,所以我们就需要用到接口适配器了:
我们定义一个抽象的类:
public abstract class BaseListener implements DownLoadListener {
@Override
public void onStart() {
}
@Override
public void onLoading() {
}
@Override
public void onSuccess() {
}
@Override
public void onFinish() {
}
}
然后:
public static void main(String[] args) {
DownLoadHelper downLoadHelper = new DownLoadHelper();
downLoadHelper.download(new BaseListener() {
@Override
public void onStart() {
super.onStart();
System.out.println("开始下载");
}
@Override
public void onSuccess() {
super.onSuccess();
System.out.println("下载成功");
}
});
}
发现了么,想用哪个方法,直接冲些就好了,不用的不需要重写。
接下来稍加改动,比如onStart是我们必须要重写的方法:
public abstract class BaseListener implements DownLoadListener {
@Override
public abstract void onStart();
@Override
public void onLoading() {
}
@Override
public void onSuccess() {
}
@Override
public void onFinish() {
}
}
一个非抽象类继承抽象类不需要实现抽象类的抽象方法,记着吧,这是Java基础:
public static void main(String[] args) {
DownLoadHelper downLoadHelper = new DownLoadHelper();
downLoadHelper.download(new BaseListener() {
@Override
public void onStart() {
System.out.println("开始下载");
}
@Override
public void onSuccess() {
super.onSuccess();
System.out.println("下载成功");
}
});
}
这里没什么变化,只是onStart这个方法必须实现,效果是一样的