责任链模式
一、概述:
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。比如有异常链、tomcat的filter链等等。
二、责任链模式涉及到的角色:
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、定义下标越界节点