定義
責任鏈模式(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,"三級日志記錄"); } }