结构型--适配器模式
一、什么是适配器模式
定义:适配器模式属于结构型模式,把一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。
适配器模式又可以分为4种类型,类适配器模式、对象适配器模式、单接口适配器模式(缺省适配器模式)和双向适配器模式。后2种模式的实现比较复杂并且在实际开发过程中很少使用。类适配器和对象适配器中,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
适配器优点:
1.能提高类的透明性和复用性,现有类的复用但不需要改变;
2.目标类和适配器类解耦合,提高程序扩展性;
3.符合开闭原则。
适配器缺点:
适配器模式编写过程中需要全面的考虑,可能会增加系统的复杂性,代码更难读懂。
二、适配器模式的结构
1、类适配器模式结构图
2、对象适配器模式的结构图
适配器模式(Adapter)包含以下主要角色:
Target:目标角色,定义了客户端期望的接口
Adaptee:适配者角色,实现了我们想要使用的功能,但是接口不匹配
Adapter:适配器角色,实现了目标接口。它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
三、模式实现示例
(1) 类适配器模式的代码如下。
package adapter; //目标接口 interface Target { public void request(); } //适配者接口 class Adaptee { public void specificRequest() { System.out.println("适配者中的业务代码被调用!"); } } //类适配器类 class ClassAdapter extends Adaptee implements Target { public void request() { specificRequest(); } } //客户端代码 public class ClassAdapterTest { public static void main(String[] args) { System.out.println("类适配器模式测试:"); Target target = new ClassAdapter(); target.request(); } }
程序的运行结果如下:
类适配器模式测试: 适配者中的业务代码被调用!
(2)对象适配器模式的代码如下。
package adapter; //对象适配器类 class ObjectAdapter implements Target { private Adaptee adaptee; public ObjectAdapter(Adaptee adaptee) { this.adaptee=adaptee; } public void request() { adaptee.specificRequest(); } } //客户端代码 public class ObjectAdapterTest { public static void main(String[] args) { System.out.println("对象适配器模式测试:"); Adaptee adaptee = new Adaptee(); Target target = new ObjectAdapter(adaptee); target.request(); } }
说明:对象适配器模式中的“目标接口”和“适配者类”的代码同类适配器模式一样,只要修改适配器类和客户端的代码即可。
程序的运行结果如下:
对象适配器模式测试: 适配者中的业务代码被调用!
四、在Spring中的应用
AOP和MVC中,都有用到适配器模式。
1. AOP中的应用
在Spring的Aop中,使用Advice(通知)来增强被代理类的功能,Advice的类型有:BeforeAdvice、AfterReturningAdvice、ThreowSadvice。
每种Advice都有对应的拦截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。
各种不同类型的Interceptor,通过适配器统一对外提供接口,如下类图所示:client ---> target ---> adapter ---> interceptor ---> advice。最终调用不同的advice来实现被代理类的增强
2. MVC中的应用
DispatcherServlet中的doDispatch方法,是将请求分发到具体的controller,因为存在很多不同类型的controller,常规处理是用大量的if...else...,来判断各种不同类型的controller,如下这样:
if(mappedHandler.getHandler() instanceof MultiActionController){ ((MultiActionController)mappedHandler.getHandler()).xxx }else if(mappedHandler.getHandler() instanceof XXX){ ... }else if(...){ ... }
如果还需要添加另外的controller,就需要再次添加if...else...,程序就会难以维护,也违反了开闭原则 -- 对扩展开放,对修改关闭。
因此,spring定义了一个适配器接口,使得每一种Controller有一种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了。
下图展示了DispatcherServlet类的关系图,因为使用了adapter