責任鏈模式
一、概述:
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。比如有異常鏈、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; //用於指定下一個異常 publicExceptionChain 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、定義下標越界節點
責任鏈模式