说明
适配器模式(Adapter)是一种结构型设计模式。顾名思义,主要作用就是用来做适配用的。之所以需要适配,是因为已有的代码不能很好的完成我们的业务逻辑,但是通过简单的适配,就可以满足我们的需求,避免重复编写很多业务代码。
应用场景
想要复用一些现有的类,但是接口与复用环境要求不一致,比如入参不同、返回结果结构不能满足需求等。
模式特征
角色 | 说明 | 举栗 |
---|---|---|
Interface(目标接口) | 客户端期望的接口 | SayHello |
Adapter(适配器) | 完成适配工作的类,实现Interface | ClassAdapter、ObjectAdapter |
Adaptee(被适配者) | 已有的功能类,待适配 | Hello |
实现方式
- 类适配器模式:Adapter直接继承Adaptee,并实现Interface
- 对象适配器模式:Adapter实现Interface,并依赖Adaptee
UML
类适配器模式
对象适配器模式
代码实现
- 被适配者:返回英文 “hello adapter”,但是我们的需求是返回中文
public class Hello {
public String hello(){
return "hello adapter";
}
}
- 目标接口:返回中文的接口
public interface SayHello {
void sayHelloInChinese();
}
- 类适配器模式
public class ClassAdapter extends Hello implements SayHello {
@Override
public void sayHelloInChinese() {
String str = super.hello();
String result = doTranslate(str);
System.out.println(result);
}
private String doTranslate(String str) {
//具体翻译实现省略
return "你好,适配器";
}
}
- 对象适配器模式
public class ObjectAdapter implements SayHello {
//依赖Hello
private Hello hello = new Hello();
@Override
public void sayHelloInChinese() {
String str = hello.hello();
String result = doTranslate(str);
System.out.println(result);
}
private String doTranslate(String str) {
//具体翻译实现省略
return "你好,适配器";
}
}
- 客户端测试类
public class Client {
public static void main(String[] args) {
//类适配器
ClassAdapter classAdapter = new ClassAdapter();
classAdapter.sayHelloInChinese();
//对象适配器
ObjectAdapter objectAdapter = new ObjectAdapter();
objectAdapter.sayHelloInChinese();
}
}
- 输出结果
你好,适配器
你好,适配器
优点
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
- 增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
- 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
顺便说一句
其实还有一种缺省适配器模式,其主要功能就是让我们可以按需实现功能。
因为对于一个接口内的方法,有时候我们并不需要实现所有方法,但是一旦我们实现接口,我们的实现类里面就必然列出了接口内的所有方法,即是我们不去实现它。这样会让人很不舒服(代码洁癖患者),而缺省适配器模式可以解决这一尴尬现象,但是我们这里不做介绍(有兴趣的可以自行了解)。
但是在Java8中提供了default关键字,可以实现缺省适配器模式的效果,直接用代码解释吧:
- 问候接口类
public interface Hello{
default void sayHelloInChinese(String name){}
default void sayHelloInEnglish(String name){}
}
- 中文问候实现
public class ChineseHello implements Hello{
@Override
public void sayHelloInChinese(String name){
System.out.println("你好:" + name);
}
}
- 英文问候实现
public class EnglishHello implements Hello{
@Override
public void sayHelloInEnglish(String name){
System.out.println("Hello:" + name);
}
}