基于面向对象和递归的拦截器设计模式

发布于:2024-07-21 ⋅ 阅读:(162) ⋅ 点赞:(0)

1 定义

拦截器模式(Interceptor Pattern),是指提供一种通用的扩展机制,可以在业务操作前后提供一些切面的(Cross-Cutting)的操作。这些切面操作通常是和业务无关的,比如日志记录、性能统计、安全控制、事务处理、异常处理和编码转换等。

在功能上,拦截器模式和面向切面编程(Aspect OrientedProgramming,AOP)的思想很相似。

推荐拦截器的实现方式的原因:

  1. 一个其命名更能表达前置处理和后置处理的含义。
  2. 拦截器的添加和删除会更加灵活。

2 设计原理

在这里插入图片描述

不同于Java的动态代理是利用Java反射机制的,拦截器模式完全是利用面向对象技术的,巧妙地使用组合模式外加递归调用实现了灵活、可扩展的前置处理和后置处理。

在拦截器模式中,主要包含以下角色:

  • TargetInvocation:包含了一组Interceptor和一个Target对象,确保在Target处理请求前后,按照定义顺序调用Interceptor做前置和后置处理。
  • Target:处理请求的目标接口。
  • Interceptor:拦截器接口。
  • InterceptorImpl:拦截器实现,用来在Target处理请求前后做切面处理。

各角色之间的关系如下类图所示:
在这里插入图片描述

编码实现

创建Target接口

public interface Target{ 
    public Response execute(Request request); 
}

创建Interceptor接口

public interface Interceptor { 
    public Response intercept(TargetInvocation targetInvocation); 
}

创建TargetInvocation


public class TargetInvocation {    
    private List<Interceptor> interceptorList = new ArrayList<>();    
    private Iterator<Interceptor> interceptors;    
    private Target target; private Request request;    
    public Response invoke(){        
        if( interceptors.hasNext() ){       
            //此处是整个算法的关键,这里会递归调用invoke()        
            Interceptor interceptor = interceptors.next();      
            interceptor.intercept(this);       
        }         
        return target.execute(request);     
    }     
    public void addInterceptor(Interceptor interceptor){         
        //添加新的Interceptor到TargetInvocation中         
        interceptorList.add(interceptor);         
        interceptors = interceptorList.iterator();     
    } 
}

创建具体的Interceptor

AuditInterceptor实现如下:

public class AuditInterceptor implements Interceptor{ 
	    @Override 
	    public Response intercept(TargetInvocation targetInvocation) {                                 
	    if(targetInvocation.getTarget() == null) { 
            throw new IllegalArgumentException("Target is null"); 
         } 
         System.out.println("Audit Succeeded "); 
         return targetInvocation.invoke(); 
     } 
}

LogInterceptor实现如下:

public class LogInterceptor implements Interceptor { 
	@Override 
	public Response intercept(TargetInvocation targetInvocation) { 
			System.out.println("Logging Begin"); 
			Response response = targetInvocation.invoke(); 
			System.out.println("Logging End"); 
			return response; 
		}
 }

InterceptorDemo演示


public class InterceptorDemo { 
	public static void main(String[] args) { 
			TargetInvocation targetInvocation = new TargetInvocation(); 
			targetInvocation.addInterceptor(new LogInterceptor()); 
			targetInvocation.addInterceptor(new AuditInterceptor()); 
			targetInvocation.setRequest(new Request()); 
			targetInvocation.setTarget(request->{return new Response();});
			 targetInvocation.invoke();
	}
 }

输出结果

Logging Begin
 Audit Succeeded
  Logging End

小结

拦截器模式在开源框架中被广泛使用,例如,MVC框架Struts2的Interceptor机制正是使用该模式,只是在Struts2中Target叫Action,TargetInvocation叫ActionInvocation。在开源流程引擎Activity中也有使用该模式,其Target叫Command。在COLA框架中,同样使用拦截器模式来进行Command的前置和后置处理。


网站公告

今日签到

点亮在社区的每一天
去签到