【14】行为型-责任链模式

1、上下文及定义

Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。


2、常用场景

(1)AOP

(2)Servlet filter


3、解决方法

      在一个链上,都有相应职责的类,因此叫Chain of Responsibility.

优点:
       因为无法预知来自外界(客户端)的请求是属于哪种类型,每个类如果碰到它不能处理的请求只要放弃就可以。

缺点:

(1)效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念优化。 在Java AWT1.0中,对于鼠标按键事情的处理就是使用CoR,到Java.1.1以后,就使用Observer代替CoR

(2)扩展性差,因为在CoR中,一定要有一个统一的接口Handler.局限性就在这里。


与Command模式区别:

Command 模式需要事先协商客户端和服务器端的调用关系,比如 1 代表 start ,2 代表 move 等,这些 都是封装在 request 中,到达服务器端再分解。

CoR 模式就无需这种事先约定,服务器端可以使用 CoR 模式进行客户端请求的猜测,一个个猜测 试验。


4、抽象模型

【14】行为型-责任链模式

aop chain

【14】行为型-责任链模式


5、代码实例

(1)模型实例

handler

public abstract class Handler
{
    /**
     * @link aggregation 
     * @supplierCardinality 0..1
     */
    protected Handler successor;

    public abstract void handleRequest();

    public void setSuccessor(Handler successor)
    {
        this.successor = successor;
    }

    public Handler getSuccessor()
    {
        return successor;
    }
}

handler实现类

public class ConcreteHandler extends Handler
{
    public void handleRequest()
    {
        if (getSuccessor() != null)
        {
            System.out.println("The request is passed to " + getSuccessor());
            getSuccessor().handleRequest();
        }
        else
        {
            System.out.println("The request is handled here.");
        }
    }
}

客户端

public class Client
{
    /**
     * @directed 
     */
    static private Handler handler1, handler2;

    public static void main(String[] args)
    {
    	handler1 = new ConcreteHandler();
    	handler2 = new ConcreteHandler();

        handler1.setSuccessor(handler2);
        handler1.handleRequest();
    }
}

(2)抽象出Request

handler接口

public interface Handler{
  public void handleRequest(Request request);
}

request类

public class Request{
  private String type;

  public Request(String type){this.type=type;}
  public String getType(){return type;}
  public void execute(){
    //request真正具体行为代码
  }
}

handler实现

public class ConcreteHandler implements Handler{
  private Handler successor;
  public ConcreteHandler(Handler successor){
    this.successor=successor;
  }
  public void handleRequest(Request request){
    if (request instanceof HelpRequest){
      //这里是处理Help的具体代码
    }else if (request instanceof PrintRequst){
      request.execute();
    }else
      //传递到下一个
      successor.handle(request);
    }
  }
}

(3)Servlet的Filter Chain

filter实例

/**
 * 整个web的编码过滤
 * 设定为UTF-8编码
 * @author: caibosi
 * @created: 2013-10-20
 * @time: 15:18:12
 */
//@WebFilter(value="/*",asyncSupported = true)
public class EncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

  具体看tomcat的ApplicationFilterChain的实现


(4)AOP的Aop Chain

aop chain

/**
 * @author caibosi
 * @created 2013-10-30
 */
public class AopChain {

    /**
     * 对一个方法的一系列拦截
     */
    private List<AopFilter> aopList;

    /**
     * 当前拦截的index
     */
    private int currentAopIndex = 0;

    /**
     * 被拦截的类
     */
    private Class<?> targetClass;

    /**
     * 被拦截的对象
     */
    private Object targetObject;

    /**
     * 被拦截的方法
     */
    private Method targetMethod;
    /**
     * 被拦截的方法的参数
     */
    private Object[] methodParams;

    /**
     * 经过拦截处理后的方法
     */
    private MethodProxy aoppedMethod;

    /**
     * 被拦截处理后的对象
     */
    private Object aoppedObject;

    public AopChain(Class<?> targetClass,Object targetObject,Method targetMethod,
                    Object[] methodParams,MethodProxy methodProxy,List<AopFilter> aopList){
        this.targetClass = targetClass;
        this.targetObject = targetObject;
        this.targetMethod = targetMethod;
        this.aoppedMethod = methodProxy;
        this.methodParams = methodParams;
        this.aopList = aopList;
    }

    /**
     * 执行当前拦截
     * 并挑战到下一个拦截
     */
    public void executeAndNext(){
        if(currentAopIndex < aopList.size()){
            AopFilter aop = aopList.get(currentAopIndex);
            //设置下一个拦截
            currentAopIndex++;
            //执行当前拦截,传入chain,拦截后继续调用chain的executeAndNext
            aop.execute(this);
        } else{
            try {
                aoppedObject = aoppedMethod.invokeSuper(targetObject,methodParams);
            } catch (Throwable throwable) {
                ExceptionTool.transformException(throwable);
            }
        }
    }

    public Class<?> getTargetClass() {
        return targetClass;
    }

    public Object getTargetObject() {
        return targetObject;
    }

    public Method getTargetMethod() {
        return targetMethod;
    }

    public Object[] getMethodParams() {
        return methodParams;
    }

    public MethodProxy getAoppedMethod() {
        return aoppedMethod;
    }

    public Object getAoppedObject() {
        return aoppedObject;
    }
}

aop filter类

/**
 * @author: caibosi
 * @created: 2013-10-31
 */
public abstract class AopFilter {
    //aop的拦截方法
    public void execute(AopChain chain) {
        Class<?> targetClass = chain.getTargetClass();
        Method targetMethod = chain.getTargetMethod();
        Object[] params = chain.getMethodParams();
        //调用模板,提供钩子方法
        begin(targetClass,targetMethod,params);
        try{
            if(filter(targetClass,targetMethod,params)){
                before(targetClass,targetMethod,params);
                chain.executeAndNext();
                after(targetClass,targetMethod,params);
            }else{
                chain.executeAndNext();
            }
        } catch (Exception e){
            /**
             * 这里catch exception,而不是throwable
             * http://www.importnew.com/7383.html
             * http://docs.oracle.com/javase/7/docs/api/
             *
             * error和exception都继承至throwalbe接口
             * 而error属于jvm系统的异常,一般无法控制
             * Error表示编译时和系统错误,通常不能预期和恢复,比如硬件故障、JVM崩溃、内存不足等
             * 因而这里不捕获,而捕获exception
             *
             * exception又分runtime exception 和checked exception
             * checked exception 一般跟外部资源有关(如文件、数据库等)
             * 自定义的exception继承至runtime exception
             *
             * throws用在方法头,用来标记该方法可能没有处理的异常,需要调用者警惕
             * throw
             *
             */
            error(targetClass,targetMethod,params,e);
        } finally {
            end(targetClass,targetMethod,params);
        }
    }

    //钩子方法,可以延迟到子类实现

    public void begin(Class<?> targetClass,Method targetMethod,Object[] params){}

    public void end(Class<?> targetClass,Method targetMethod,Object[] params){}

    public boolean filter(Class<?> targetClass,Method targetMethod,Object[] params){
        return true;
    }

    public void before(Class<?> targetClass, Method targetMethod, Object[] params) {}

    public void after(Class<?> targetClass, Method targetMethod, Object[] params) {}

    public void error(Class<?> targetClass, Method targetMethod, Object[] params, Exception e){}

}

aop factory

/**
 * @author caibosi
 * @created 2013-10-30
 */
public class AopFactory {

    public static <T> T getAoppedObject(final Class<?> targetClass,final List<AopFilter> aopList){
        return (T) Enhancer.create(targetClass,new MethodInterceptor() {
            @Override
            public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                AopChain aopChain = new AopChain(targetClass,target,method,args,methodProxy,aopList);
                aopChain.executeAndNext();
                return aopChain.getAoppedObject();
            }
        });
    }
}


你可能感兴趣的:(【14】行为型-责任链模式)