1. 程式人生 > >責任鏈模式

責任鏈模式

響應 tom void req str 信息 bounds art .get

一、概述:

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

責任鏈模式