责任链模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了责任链模式相关的知识,希望对你有一定的参考价值。

一、概述:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。比如有异常链、tomcatfilter链等等。

 

二、责任链模式涉及到的角色:

1、抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。

2、具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

 

三、这里用异常链来做具体说明(定义三个链节点)

1、定义一个抽象处理角色(这里会多定义一个响应方法,用于处理双链机制)

public abstract class ExceptionChain {
    public abstract void handleRequset(String exception); //处理请求异常信息
    public abstract void handleResponse(String exception); //处理响应异常    
    private ExceptionChain nextException;  //用于指定下一个异常
    public ExceptionChain getNextException() {
        return nextException;
    }
    public void setNextException(ExceptionChain nextException) {
        this.nextException = nextException;
    }    
}

2、定义一个空指针异常节点

public class NullPointerException extends ExceptionChain {
    @Override
    public void handleRequset(String exception) {
        if("NullPointerException".equals(exception)){
            System.out.println("空指针异常:NullPointerException");
        }else{
            System.out.println("空指针异常无法处理:NullPointerException");
            if(this.getNextException()!=null){
                this.getNextException().handleRequset(exception);
            }
        }
        this.handleResponse(exception); //把处理结果放在这里,就可以实现双链处理结果,跟递归思想类似
    }
    @Override
    public void handleResponse(String exception) {
        System.out.println("空指针异常返回处理结果:"+exception);
    }
}

3、定义一个下标越界异常节点

public class IndexOutOfBoundsException extends ExceptionChain {
    @Override
    public void handleRequset(String exception) {
        if("IndexOutOfBoundsException".equals(exception)){
            System.out.println("下标越界异常:IndexOutOfBoundsException");
        }else{
            System.out.println("下标越界异常无法处理:IndexOutOfBoundsException");
            if(this.getNextException()!=null){
                this.getNextException().handleRequset(exception);
            }
        }
        this.handleResponse(exception);
    }
    @Override
    public void handleResponse(String exception) {
        System.out.println("下标越界异常返回处理结果:"+exception);
    }
}

4定义运行时异常节点

public class RuntimeException extends ExceptionChain {
    @Override
    public void handleRequset(String exception) {
        if("RuntimeException".equals(exception)){
            System.out.println("运行时异常:RuntimeException");
        }else{
            System.out.println("运行时异常无法处理:RuntimeException");
            if(this.getNextException()!=null){            
                this.getNextException().handleRequset(exception);
            }
        }
        this.handleResponse(exception);
    }

    @Override
    public void handleResponse(String exception) {
        System.out.println("运行时异常返回处理结果:"+exception);
    }

5这样我们的就可以实现责任链了,测试类

public class ExceptionClient {
    public static void main(String[] args) {
        ExceptionChain nullPointerException = new NullPointerException();  //空指针处理
        ExceptionChain indexOutOfBoundsException = new IndexOutOfBoundsException();  //下标越界异常
        ExceptionChain runtimeException = new RuntimeException();  //运行时异常
        
        //设置链的对应关系
        nullPointerException.setNextException(indexOutOfBoundsException); 
        indexOutOfBoundsException.setNextException(runtimeException);
        
        nullPointerException.handleRequset("RuntimeException");
    }
}

运行结果:

技术分享

可以看出,响应处理是与请求逆向的,这就实现了双链机制。

6这时如果我们要在空指针异常处理和下标越界处理中添加一个IO异常,那可以这样实现

  • 定义一个IO节点
public class IOException extends ExceptionChain {
    @Override
    public void handleRequset(String exception) {
        if("IOException".equals(exception)){
            System.out.println("IO异常:IOException");
        }else{
            System.out.println("IO异常无法处理:IOException");
            if(this.getNextException()!=null){            
                this.getNextException().handleRequset(exception);
            }
        }
        this.handleResponse(exception);
    }

    @Override
    public void handleResponse(String exception) {
        System.out.println("IO异常处理结果:"+exception);
    }
}
  • 修改测试类

public class ExceptionClient {
    public static void main(String[] args) {
        ExceptionChain nullPointerException = new NullPointerException();  //空指针处理
        ExceptionChain indexOutOfBoundsException = new IndexOutOfBoundsException();  //下标越界异常
        ExceptionChain runtimeException = new RuntimeException();  //运行时异常
        ExceptionChain ioException = new IOException();  //运行时异常
        
        //设置链的对应关系
        nullPointerException.setNextException(ioException); 
        ioException.setNextException(indexOutOfBoundsException);
        indexOutOfBoundsException.setNextException(runtimeException);
        
        nullPointerException.handleRequset("RuntimeException");
    }
}
  • 运行结果就是:

   技术分享

从这里可以看出,连接节点没什么相应的耦合关系,只需要配置好链节点之间的关系即可

 

四、用数组的方式还实现一下责任链

 

1定义一个抽象处理角色

public abstract class MyException {
    //处理请求异常信息,exceptionChain用于处理双链机制
    public abstract void handleRequset(ExceptionChain exceptionChain ,String exception);

    //处理响应异常结果
    public abstract void handleResponse(String exception); 
}

2定义一个异常链,用于处理异常节点的关系

public class ExceptionChain extends MyException {
    
    public List<MyException> exceptionChainList = new ArrayList<MyException>();
    
    //添加异常节点,这里返回异常链有利于美化代码(个人观点),在测试类体现
    public ExceptionChain addException(MyException exception){
        this.exceptionChainList.add(exception);
        return this;
    }
    
    public int flag=0;

    @Override
    public void handleRequset(ExceptionChain exceptionChain,String exceptionStr) {
        //类似递归,这里每次调用都会获取第flag个处理的节点,然后flag+1,即下次进来会获取下个节点
        if(flag==exceptionChainList.size()) return;    
        MyException exception = exceptionChainList.get(flag);
        flag++;
        exception.handleRequset(exceptionChain, exceptionStr);    
    }

    @Override
    public void handleResponse(String exception) {
    }
}

3定义io异常节点

public class IOException extends MyException {

    @Override
    public void handleRequset(ExceptionChain exceptionChain,String exceptionStr) {
        if("IOException".equals(exceptionStr)){
            System.out.println("IO异常请求处理");
            handleResponse(exceptionStr);
            return;
        }else{
            System.out.println("IO异常请求没法处理");
            exceptionChain.handleRequset(exceptionChain, exceptionStr);
            handleResponse(exceptionStr);
        }    
    }

    @Override
    public void handleResponse(String exceptionStr) {
        System.out.println("IO异常响应处理");
    }
}

4定义空指针异常节点

public class NullPointerException extends MyException {

    @Override
    public void handleRequset(ExceptionChain exceptionChain,String exceptionStr) {
        if("NullPointerException".equals(exceptionStr)){
            System.out.println("空指针异常请求处理");
            handleResponse(exceptionStr);
            return;
        }else{
            System.out.println("空指针异常请求没法处理");
            exceptionChain.handleRequset(exceptionChain, exceptionStr);
            handleResponse(exceptionStr);
        }    
    }

    @Override
    public void handleResponse(String exception) {
        System.out.println("空指针异常响应处理");

    }
}

5定义下标越界异常节点

public class IndexOutOfBoundsException extends MyException {

    @Override
    public void handleRequset(ExceptionChain exceptionChain,String exceptionStr) {
        if("IndexOutOfBoundsException".equals(exceptionStr)){
            System.out.println("下标越界异常请求处理");
            handleResponse(exceptionStr);
            return;
        }else{
            System.out.println("下标越界异常请求没法处理");
            exceptionChain.handleRequset(exceptionChain, exceptionStr);
            handleResponse(exceptionStr);
        }    
    }

    @Override
    public void handleResponse(String exception) {
        System.out.println("下标越界异常响应处理");

    }

6代码已经实现,我们这里写个测试类

public class ArrayExceptionClient {
    public static void main(String[] args) {
        ExceptionChain chain = new ExceptionChain();
        //下面这个语句就是我认为代码美化的地方
        chain.addException(new IOException())
             .addException(new NullPointerException())
             .addException(new IndexOutOfBoundsException());
        
        chain.handleRequset(chain,"IndexOutOfBoundsException");
    }
}

输出结果:

     技术分享

可以看到,我上面异常链ExceptionChain 也继承了MyException ,这样的好处就是我可以把一个异常链当成一个异常节点处理,可以实现异常链与异常链之间的叠加,比如上面的测试类我可以写成

public class ArrayExceptionClient {
    public static void main(String[] args) {
        ExceptionChain chain = new ExceptionChain();
        //下面这个语句就是我认为代码美化的地方
        chain.addException(new IOException())
             .addException(new NullPointerException());
        
        //再定义一个链
        ExceptionChain chaintemp = new ExceptionChain();
        chaintemp.addException(new IndexOutOfBoundsException());
        
        chain.addException(chaintemp);
        chain.handleRequset(chain,"IndexOutOfBoundsException");
    }
}

这样的处理结果是一致的。

 

Done!   O(_)O

 

 

3、定义下标越界节点

以上是关于责任链模式的主要内容,如果未能解决你的问题,请参考以下文章

JS设计模式责任链设计模式的代码示例

设计模式----责任链模式

责任链模式

(十五)责任链模式-代码实现

设计模式之责任链模式

责任链模式