适配器模式
定义: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
通俗一些就是两个不同、没有关联的接口,如果通过一个适配器或者拦截器,可以进行一起协作。
优点:
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 灵活性好。
缺点: 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接 口的实现,一个系统如果太多出现这种情况,无异于一场灾难。
Spring Aop适配器+代理模式案例
Spring架构中涉及了很多设计模式,本文来介绍下Spring中在AOP实现时Adapter模式的使用。AOP本质上是Java动态代理模式的实现和适配器模式的使用。
我们基于Spring的前置通知来实现一个打卡案例,再基于前置通知讲解前置适配模式。
创建打卡接口: PunchCard 定义打卡方法,代码如下:
public interface PunchCard {
//打卡记录
void info(String name);
}
定义打卡实现: PunchCardImpl 实现打卡操作,代码如下:
public class PunchCardImpl implements PunchCard {
@Override
public void info(String name) {
System.out.println(name+" 打卡成功!");
}
}
前置通知创建: PunchCardBefore 实现在打卡之前识别用户身份,代码如下:
public class PunchCardBefore implements MethodBeforeAdvice {
@Override public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("身份识别通过!");
}
}
spring.xml配置前置通知:
<!--打卡-->
<bean id="punchCard" class="com.itheima.adapter.PunchCardImpl"></bean>
<!--前置通知-->
<bean id="punchCardBefore" class="com.itheima.adapter.PunchCardBefore"></bean>
<!--代理配置-->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定目标对象 -->
<property name="target" ref="punchCard"/>
<!-- 指定目标类实现的所有接口 -->
<property name="interfaces" value="com.itheima.adapter.PunchCard"/>
<!-- 指定切面 -->
<property name="interceptorNames" >
<list>
<value>punchCardBefore</value>
</list>
</property>
</bean>
测试效果如下:
正在初始化打卡程序!
王五 打卡成功!
Spring AOP适配器体系
前置通知其实就是适配器模式之一,刚才我们编写的前置通知实现了接口 MethodBeforeAdvice。Spring容器将每 个具体的advice封装成对应的拦截器,返回给容器,这里对advice转换就需要用到适配器模式。我们来分析下适配器 的实现:
如下代码实现了接口 BeforeAdvice,而 BeforeAdvice继承了 Advice接口,在适配器接口 AdvisorAdapter里面 定义了方法拦截。
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}
AdvisorAdapter:定义了2个方法,分别是判断通知类型是否匹配,如果匹配就会获取对应的方法拦截。
public interface AdvisorAdapter {
// 判断通知类型是否匹配
boolean supportsAdvice(Advice advice);
// 获取对应的拦截器
MethodInterceptor getInterceptor(Advisor advisor);
}
MethodBeforeAdviceAdapter:实现了 AdvisorAdapter,代码如下:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 通知类型匹配对应的拦截器
return new MethodBeforeAdviceInterceptor(advice);
}
}
刚才我们在spring.xml中配置了代理类,代理类通过DefaultAdvisorAdapterRegistry类来注册相应的适配器,我们可以在