設計模式-責任鏈模式(17)


定義

責任鏈模式(Chain of Responsibility Pattern)是一種常見的行為模式。

責任鏈模式英文原話是:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving object and pass the request along the chain until an object handles it.

翻譯:使多個對象都有處理請求的機會,從而避免了請求的發送者和接收者之間的耦合關系。將這些對象串成一條鏈,並沿着這條鏈一直傳遞該請求,直到有對象處理它為止。

責任鏈模式的重點在“鏈上”,由一條鏈去處理相似的請求,在鏈中決定誰來處理這個請求,並返回相應的結果。

角色:

抽象處理者(Handler)角色:該角色對請求進行抽象,並定義一個方法來設定和返回對下一個處理者的引用。

具體處理者(Concrete Handler):該角色接到請求后,可以選擇將請求處理掉,或者將請求傳給下一個處理者。由於具體處理者持有對下一個處理者的引用,因此,如果需要,處理者可以訪問下一個處理者。

/**
 * 抽象處理器
 */
public abstract class Handler {
    //下一個處理器
    private Handler nextHandler;

    //處理方法
    public abstract void handleRequest();

    public Handler getNextHandler() {
        return nextHandler;
    }
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

/**
 * 具體處理器.
 */
public class ConcreteHandler extends Handler {

    @Override
    public void handleRequest() {
        System.out.println(this.toString()+"處理器處理");
        if (getNextHandler()!=null){   //判斷是否存在下一個處理器
            getNextHandler().handleRequest();   //存在則調用下一個處理器
        }
    }

}

/**
 * 測試
 */
public class Client {
    public static void main(String[] args) {
        Handler h1 = new ConcreteHandler();
        Handler h2 = new ConcreteHandler();
        h1.setNextHandler(h2);   //h1的下一個處理器是h2
        h1.handleRequest();
    }
}

源碼

優點

  • 責任鏈模式將請求和處理分開,請求者不知道是誰處理的,處理者可以不用知道請求的全貌。
  • 提高系統的靈活性。

缺點

  • 降低程序的性能。每個請求都是從鏈頭遍歷到鏈尾,當鏈比較長的時候,性能會大幅下降。
  • 不易於調試。由於該模式采用了類似遞歸的方式,調試的時候邏輯比較復雜。

應用場景

責任鏈模式是一種常見的模式,Struts2的核心控件FilterDispatcher是一個Servlet過濾器,該控件就是采用責任鏈模式,可以對用戶請求進行層層過濾處理。責任鏈模式在實際項目中的使用比較多,其典型的應用場景如下:

  • 一個請求需要一系列的處理工作。
  • 業務流的處理,例如文件審批。
  • 對系統進行擴展補充。
/**
 * 抽象處理器.
 */
public abstract class AbstractLogger {
    public static final int INFO = 1;    //一級日志
    public static final int DEBUG = 2;   //二級日志包括一級
    public static final int ERROR = 3;   //三級包括前兩個

    protected int level;
    //責任鏈下一個元素
    protected AbstractLogger nextLogger ;
    public void setNextLogger(AbstractLogger nextLogger){
        this.nextLogger = nextLogger;
    }

    //不同級別的記錄方法不一樣,這里給一個抽象的記錄方法
    abstract protected void write(String message);

    //調用責任鏈處理器的記錄方法.並且判斷下一個責任鏈元素是否存在,若存在,則執行下一個方法.
    public void logMessage(int level,String message){
        if (this.level <= level){    //根據傳進來的日志等級,判斷哪些責任鏈元素要去記錄
            write(message);
        }
        if (nextLogger != null){
            nextLogger.logMessage(level,message);   //進行下一個責任鏈元素處理
        }
    }
}

/**
 * 控制台處理器.
 */
public class ConsoleLogger extends AbstractLogger {
    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Standard Console::Logger :"+message);
    }
}

/**
 * 文件處理器.
 */
public class FileLogger extends AbstractLogger {
    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("File Console::Logger"+message);
    }
}

/**
 * error日志處理器.
 */
public class ErrorLogger extends AbstractLogger {
    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error Console::Logger: " + message);
    }
}

/**
 * 處理鏈.
 */
public class ChainPatternDemo {

    public static AbstractLogger getChainOfLoggers() {

        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);

        return  errorLogger;
    }
}

public class Main {
    public static void main(String[] args) {
        AbstractLogger logger = ChainPatternDemo.getChainOfLoggers();
        logger.logMessage(1,"一級日志記錄");
        System.out.println("--------------------------------");
        logger.logMessage(2,"二級日志記錄");
        System.out.println("--------------------------------");
        logger.logMessage(3,"三級日志記錄");
    }
}

  源碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM