定义
- 将一个类的接口(被适配者)转换成客户期望的另一个接口(目标)
- 使原本接口不兼容的类可以一起工作
类型
- 结构型
适用场景
- 已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)
- 不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案
优点
- 能提高类的透明性和复用,现有的类复用但不需要改变(解决了现有类和目标类不匹配的问题)
- 目标类和适配器类解耦,提高程序扩展性
- 符合开闭原则(具体的实现都在适配器中,客户端知道的只有适配器类,如果需要扩展,只需要扩展适配器类,而原有的类是不需要变化的)
缺点
- 适配器模式编写过程需要全面考虑,可能会增加系统的复杂性
- 增加系统代码可读难度
- 如果过多的使用适配器模式,会让我们的系统变得凌乱,不易整理,比如我们调用一个接口。其实内部已经被是配成了另一个接口实现。
扩展
- 对象适配器模式
复合组合复用原则,并且使用委托机制 - 类适配器模式
通过类继承来实现的
相关设计模式
-
适配器模式和外观模式
两者都是对现有的类或系统的封装, 外观模式 1.定义一个新的接口。 2.在现有的系统中提供一个更为方便的访问入口。 适配器模式 1.复用一个原有的接口。 2.使两个已有的接口协同工作。
代码示例
角色
- 被适配者Adaptee
- 目标接口Target
- 适配者Adapter
类适配器模式
步骤
- 创建被适配者
//被适配者
public class Adaptee {
public void apapteeRequest(){
System.out.println("被适配者的方法");
}
}
- 创建目标接口
//目标接口
public interface Target {
void request();
}
创建具体的目标类
//具体目标类
public class ConcreteTarget implements Target {
@Override
public void request() {
System.out.println("ConcreteTarget 目标方法");
}
}
- 创建适配者,继承被适配者,实现目标接口方法
//通过Adapter把Adaptee.apapteeRequest()适配给了Target.request()
public class Adapter extends Adaptee implements Target{
@Override
public void request() {
//...可添加各种逻辑代码
super.apapteeRequest();
}
}
UML
通过类图我们可以看出,Adapter(适配者)继承了Adaptee(被适配者)同时实现了Target(目标接口)。这样Target其实是有两种实现的,一种是ConcreteTarget(具体目标实现),另一个种是通过Adapter适配成Adaptee.apapteeRequest()实现
Test
测试代码
public class Test {
public static void main(String[] args) {
Target target1 = new ConcreteTarget();
target1.request();
Target target2 = new Adapter();
target2.request();
}
}
执行结果
ConcreteTarget 目标方法
被适配者的方法
对象适配器模式
对与从类适配器模式到对象适配器模式的演进,我们的被适配者Adaptee和目标Target是都不会发生改变的。我们只需要修改适配者Adapter即可
步骤
- 我们只会实现Target接口。通过组合的方式。把具体的requet()委托给Adaptee来实现。
public class Adapter implements Target {
Adaptee adaptee = new Adaptee();
@Override
public void request() {
//....添加逻辑代码
adaptee.apapteeRequest();
}
}
UML
Test
与类适配器模式相同
执行结果不变
ConcreteTarget 目标方法
被适配者的方法
生活场景
手机充电。民用电是220V的交流电,假设我们手机充电需要5V的直流电。并且手机会带电源适配器,它的作用就是把220V的交流电转化成5V的直流电。我们用对象适配器模拟这个生活场景。(在继承和组合的时候我们优先选择组合)
步骤
- 创建被适配者 220V交流电
public class AC220 {
public int outputAC220V(){
int output= 220;
System.out.println("输出民用交流电" + output + "V");
return output;
}
}
- 目标 输出5V的直流电
public interface DC5 {
int outputDC5V();
}
- 适配者 电源适配器
public class PowerAdapter implements DC5{
//将220V的交流电组合进来
private AC220 ac220 = new AC220();
@Override
public int outputDC5V() {
//适配器输入电压
int adapterInput = ac220.outputAC220V();
//变压逻辑
int outPut = adapterInput/44;
//电源适配器输出电压
System.out.println("电源适配器: 输入交流电:" + adapterInput + "V,输出直流电:"+ outPut + "V");
return adapterInput;
}
- Test
public class Test {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter();
int inputDc = dc5.outputDC5V();
}
}
执行结果
输出民用交流电220V
电源适配器: 输入交流电:220V,输出直流电:5V