适配器模式

定义: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

通俗一些就是两个不同、没有关联的接口,如果通过一个适配器或者拦截器,可以进行一起协作。

优点:

  1. 可以让任何两个没有关联的类一起运行。
  2. 提高了类的复用。
  3. 灵活性好。

缺点: 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 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适配器体系

java 适配器实例 适配器模式 spring_设计模式


前置通知其实就是适配器模式之一,刚才我们编写的前置通知实现了接口 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类来注册相应的适配器,我们可以在

java 适配器实例 适配器模式 spring_java 适配器实例_02