責任鏈模式(Chain of Responsibility Pattern)爲一個請求建立了一個接收者對象的鏈。在這種模式中,一般每一個接收者都包含對另外一個接收者的引用,若是一個接收者對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推,直到請求被處理爲止。這種模式對請求的發送者和處理者進行解耦,屬於行爲型模式。java
意圖:避免請求發送者與接收者耦合在一塊兒,讓多個對象都有可能接收請求,將這些對象鏈接成一條鏈,而且沿着這條鏈傳遞請求,直到有對象處理它爲止。mybatis
主要解決:職責鏈上的處理者負責處理請求,客戶只須要將請求發送到職責鏈上便可,無須關心請求的處理細節和請求的傳遞,因此職責鏈將請求的發送者和請求的處理者解耦了。jsp
什麼時候使用:在處理消息的時候以過濾不少道。ide
如何解決:攔截的類都實現統一接口。性能
關鍵代碼:Handler 裏面聚合它本身,在 HandlerRequest 裏判斷是否合適,若是沒達到條件則向下傳遞,向誰傳遞以前 set 進去。this
應用實例: 一、紅樓夢中的"擊鼓傳花"。 二、JS 中的事件冒泡。 三、JAVA WEB 中 Apache Tomcat 對 Encoding 的處理,Struts2 的攔截器,jsp servlet 的 Filter。spa
優勢: 一、下降耦合度。它將請求的發送者和接收者解耦。 二、簡化了對象。使得對象不須要知道鏈的結構。 三、加強給對象指派職責的靈活性。經過改變鏈內的成員或者調動它們的次序,容許動態地新增或者刪除責任。 四、增長新的請求處理類很方便。debug
缺點: 一、不能保證請求必定被接收。 二、系統性能將受到必定影響,並且在進行代碼調試時不太方便,可能會形成循環調用。 三、可能不容易觀察運行時的特徵,有礙於除錯。設計
使用場景: 一、有多個對象能夠處理同一個請求,具體哪一個對象處理該請求由運行時刻自動肯定。 二、在不明確指定接收者的狀況下,向多個對象中的一個提交一個請求。 三、可動態指定一組對象處理請求。調試
注意事項:在 JAVA WEB 中遇到不少應用。
咱們建立抽象類 AbstractLogger,帶有詳細的日誌記錄級別。而後咱們建立三種類型的記錄器,都擴展了 AbstractLogger。每一個記錄器消息的級別是否屬於本身的級別,若是是則相應地打印出來,不然將不打印並把消息傳給下一個記錄器。
建立抽象的記錄器類。
package com.cn.design_pattern.chain_of_responsibility_pattern; /** * * 抽象的責任鏈父類,定義了詳細的日誌等級 * */ public abstract class AbstractLogger { public static int INFO = 1; public static int DEBUG = 2; public static int ERROR = 3; protected int level; // 責任鏈中的下一個元素 protected AbstractLogger nextLogger; public void setNextLogger(AbstractLogger nextLogger) { this.nextLogger = nextLogger; } public void logMessage(int level, String message) { if (this.level <= level) { write(message); } if (nextLogger != null) { nextLogger.logMessage(level, message); } } abstract protected void write(String message); }
建立擴展了該記錄器類的實體類。
package com.cn.design_pattern.chain_of_responsibility_pattern.impl; import com.cn.design_pattern.chain_of_responsibility_pattern.AbstractLogger; 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); } }
package com.cn.design_pattern.chain_of_responsibility_pattern.impl; import com.cn.design_pattern.chain_of_responsibility_pattern.AbstractLogger; 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); } }
package com.cn.design_pattern.chain_of_responsibility_pattern.impl; import com.cn.design_pattern.chain_of_responsibility_pattern.AbstractLogger; public class FileLogger extends AbstractLogger { public FileLogger(int level) { this.level = level; } @Override protected void write(String message) { System.out.println("File::Logger: " + message); } }
建立不一樣類型的記錄器。賦予它們不一樣的錯誤級別,並在每一個記錄器中設置下一個記錄器。每一個記錄器中的下一個記錄器表明的是鏈的一部分。
package com.cn.design_pattern.chain_of_responsibility_pattern; import com.cn.design_pattern.chain_of_responsibility_pattern.impl.ConsoleLogger; import com.cn.design_pattern.chain_of_responsibility_pattern.impl.ErrorLogger; import com.cn.design_pattern.chain_of_responsibility_pattern.impl.FileLogger; public class Main { private 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 static void main(String[] args) { AbstractLogger loggerChain = getChainOfLoggers(); loggerChain.logMessage(AbstractLogger.INFO, "This is an information."); loggerChain.logMessage(AbstractLogger.DEBUG, "This is an debug level information."); loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information."); } }
執行程序,輸出結果:
Standard Console::Logger: This is an information. File::Logger: This is an debug level information. Standard Console::Logger: This is an debug level information. Error Console::Logger: This is an error information. File::Logger: This is an error information. Standard Console::Logger: This is an error information.
在責任鏈的設計中,首先須要抽象出一個全部過濾器的父類,並定義處理請求的方法。
而後能夠實現多個過濾器的子類,分別重寫本身的過濾器方法,即每個子過濾器的功能不一樣。
要注意,由於過濾器是一個鏈,因此,多個過濾器實現類是存在執行的先後順序的。因此前面的過濾器,須要持有下一個過濾器對象,在處理方法中,執行完本身的邏輯後,經過這個對象,來調用下一個過濾器方法。
直到過濾器所有運行完畢,再將處理後的請求丟給真正的接收者。
JAVA 的filter dubbo的過濾器,mybatis的plugins都是基於責任鏈模式
public final class ApplicationFilterChain implements FilterChain { private int pos = 0; //當前執行filter的offset private int n; //當前filter的數量 private ApplicationFilterConfig[] filters; //filter配置類,經過getFilter()方法獲取Filter private Servlet servlet @Override public void doFilter(ServletRequest request, ServletResponse response) { if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = filterConfig.getFilter(); filter.doFilter(request, response, this); } else { // filter都處理完畢後,執行servlet servlet.service(request, response); } } }