概述
记录了适配器模式的概念以及代码实现
定义
简单来说,适配器模式就是要将一个接口转换成另一个接口,大多数情况都是功能扩展之后用了新的接口,但是底层还是用的过去的接口,需要将新的接口转换成旧的才能使用。
例如我们用的充电器也是一种适配器。下面我会以翻译作为例子来说明适配器模式。
类图
当马布里来中国打球的时候,他并不会说中文,所以讲战术只能说英文那么就需要翻译,翻译也相当于是一个适配器。
Target:说中文战术
Adapter:翻译(适配器)
Adeptee:要适配的类(说英文战术)
翻译就是吧英文翻译成中文。
适配器有类适配器和对象适配器两种,下面详细介绍。
类适配器
还是用上面翻译的例子,现在我的需求是把说英文的接口转换成说中文的。
下面的类就是需要适配的,他现在只会说英文战术
interface SpeakEnglish {
void speakEnglish(String name, String tactics);
}
//需要适配的类
public class ForeignPlayer implements SpeakEnglish {
@Override
public void speakEnglish(String name, String tactics) {
System.out.println(name + "说英文:" + tactics + "战术");
}
}
目标:
interface SpeakChinese {
void speakChinese(String name,String tactics);
}
public class NativePlayer implements SpeakChinese{
@Override
public void speakChinese(String name, String tactics) {
System.out.println(name+"说中文:"+tactics+"战术");
}
}
类适配器使用继承实现适配器
public class Adapter extends ForeignPlayer implements SpeakChinese {
@Override
public void speakChinese(String name, String tactics) {
super.speakEnglish(name,tactics);
System.out.println("翻译成了中文");
}
}
Client
public class Client {
public static void main(String[] args) {
SpeakEnglish foreignPlayer = new ForeignPlayer();
SpeakChinese adapter = new Adapter();
adapter.speakChinese("马布里","二三联防");
}
}
这样,就从SpeakEnglish转换成了SpeakChinese接口
但是实际上这里使用继承实现的
不满足合成复用原则的:尽量使用对象组合,而不是继承来达到复用的目的。
所以下面改进一下,实现对象适配器
对象适配器
使用组合而非继承。要修改的地方并不多:
修改适配器
public class Adapter implements SpeakChinese{
private SpeakEnglish foreignPlayer;
public Adapter(SpeakEnglish foreignPlayer) {
this.foreignPlayer=foreignPlayer;
}
@Override
public void speakChinese(String name, String tactics) {
foreignPlayer.speakEnglish(name,tactics);
System.out.println("翻译成了中文");
}
}
Client:
public class Client {
public static void main(String[] args) {
SpeakEnglish foreignPlayer = new ForeignPlayer();
SpeakChinese adapter = new Adapter(foreignPlayer);
adapter.speakChinese("马布里","二三联防");
}
}
使用场景
- 两个类所做的事情相同或相似,但是具有不同的接口时使用
- 系统发展,产生了功能类似但是不同的接口时使用
- 所以适配器大多是无奈之举
- SpringMVC中HandlerAdapter
- AOP中所有的通知都会转化成环绕通知,转化的事Interceptor接口,这里就是用的也是适配器模式。
优点
- 提高了代码的复用性,不需要重新写代码,通过适配器就重用已有代码
- 解决目标类和适配者类不一致的问题
- 能让客户端透明访问目标接口
小结
只有写代码才知道自己是不是真的会了,中间出了好多小问题,比如接口类型只能调用接口类型的方法,继承父类是得不到实例化对象的属性值,实例对象和类完全是两码事。