一、定义
定义:将一个类的接口转换成客户期望的另一个接口
使原本接口不兼容的类可以一起工作
类型:结构型
例如笔记本电源适配器
二、适用场景
1、已经存在的类,它的方法和需要不匹配(方法结果相同或相似)
2、不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案。
三、优点
能提高类的透明性和复用,现有的类复用但不需要改变
目标类和适配器类解耦,提高程序的扩展性
符合开闭原则
四、缺点
适配器编写过程需要全面考虑,可能会增加系统的复杂性
增加系统代码可读的难度
五、扩展
对象适配器
类适配器。
如果两个选择的话,优先选择对象适配器。
六、相关模式
1、适配器模式和外观模式
适配器模式: 复用原来的接口;使两个已有的接口协同工作。
外观模式: 定义新的接口; 在现有的系统中提供一个更为方便的访问入口。适配整个相关的子系统,外观针对的力度更大。
七、Coding 类适配器
1. 创建Adaptee类
/** * 被适配者 */ public class Adaptee { public void adapteeRequest(){ System.out.println("被适配者的方法"); } }
2. 创建Target接口
/** * 目标 */ public interface Target { void request(); }
3. 创建ConcreteTarget 类
public class ConcreteTarget implements Target { @Override public void request() { System.out.println("ConcreteTarget目标方法"); } }
4. 创建Adapter 类,do something可以对方法进行扩展
public class Adapter extends Adaptee implements Target{ @Override public void request() { //do something super.adapteeRequest(); //do something } }
5. 测试
public class Test { public static void main(String[] args) { Target target = new ConcreteTarget(); target.request(); Target adapterTarget = new Adapter(); adapterTarget.request(); } }
6. UML图
八、Coding 对象适配器
与类适配器的区别为:适配器类与被继承类不是继承关系,而是组合关系
1. Adaptee类,ConcreteTarget类,Target接口,Test类与商品类适配器是相同的。
不同的是Adapter类
public class Adapter implements Target{ private Adaptee adaptee = new Adaptee(); @Override public void request() { //do something adaptee.adapteeRequest(); //do something } }
2. UML图
九、Coding 对象适配器(将220V交流电转为手机5V直流电的适配器)
1.创建AC220 类
/** * 220V 交流电 */ public class AC220 { public int outputAC220V(){ int output = 220; System.out.println("输出交流电" + output + "V"); return output; } }
2. 创建接口DC5(目标接口)
public interface DC5 { //输出5V直流电 int outputDC5V(); }
3. 创建适配器类
public class PowerAdapter implements DC5{ private AC220 ac220 = new AC220(); @Override public int outputDC5V() { int adapterInput = ac220.outputAC220V(); //变压器。。。 int adapterOutput = adapterInput/ 44; System.out.println("使用PowerAdapter输入AC:" + adapterInput + " V" + " 输出直流电:" + adapterOutput + "V"); return adapterOutput; } }
这里假设使用变压器将220V转为5V
4. 测试
public class Test { public static void main(String[] args) { DC5 dc5 = new PowerAdapter(); dc5.outputDC5V(); } }
十、在JDK或其他源码中的使用
1、JDK中的XmlAdapter。处理Xml序列化和反序列化使用的。例如将日期指定固定的格式,需要实现
XmlAdapter中的marshal和unmarshal方法。
如下图adapters文件加下都是适配器
2. Spring AOP中的AdvisorAdapter接口
public interface AdvisorAdapter { boolean supportsAdvice(Advice var1); MethodInterceptor getInterceptor(Advisor var1); }
比如其中一个类实现了AdvisorAdapter接口
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { MethodBeforeAdviceAdapter() { } public boolean supportsAdvice(Advice advice) { return advice instanceof MethodBeforeAdvice; } public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } }
3. Spring MVC中使用的HandlerAdapter接口