責任鏈模式
比如一個web請求,有一堆的過濾器需要處理(或不處理)這個請求,而這一堆接收此次請求的過濾器對象形成一條調用鏈,即為責任鏈模式
- 定義:為請求創建一個接收此次請求對象的鏈
- 類型:行為型
- 適用場景:一個請求的處理需要多個對象當中的一個或幾個協作處理
- 優點:
- 請求的發送者和接收者(請求的處理)解耦
- 責任鏈可以動態組合
- 缺點:
- 責任鏈太長或者處理時間過長,影響性能
- 責任鏈有可能過多
- 相關設計模式
- 責任鏈模式和狀態模式:責任鏈模式當中各個對象并不指定下一個處理的對象者是誰,只有在客戶端來設定鏈條中的順序以及元素,直到被某個元素處理,或者整個鏈條結束,狀態模式是讓每個狀態模式知道自己下一個處理的對象是誰,也就是說在編譯時就設定好了,這個是他倆最大的區別。
Coding
public class Course { private String name; private String article; private String video; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } public String getVideo() { return video; } public void setVideo(String video) { this.video = video; } @Override public String toString() { return "Course{" + "name='" + name + '\'' + ", article='" + article + '\'' + ", video='" + video + '\'' + '}'; } } public abstract class Approver { protected Approver approver; public void setNextApprover(Approver approver) { this.approver = approver; } public abstract void deploy(Course course); } public class ArticleApprover extends Approver { @Override public void deploy(Course course) { if (course.getArticle() != null) { System.out.println(course.getName() + "含有手記,批準"); if (approver != null) { approver.deploy(course); } } else { System.out.println(course.getName() + "不含有手記,不批準,流程結束"); } } } public class VideoApprover extends Approver { @Override public void deploy(Course course) { if (course.getVideo() != null) { System.out.println(course.getName() + "含有視頻,批準"); if (approver != null) { approver.deploy(course); } } else { System.out.println(course.getName() + "不含有視頻,不批準,流程結束"); } } }
測試
public class Test { public static void main(String[] args) { Approver articleApprover = new ArticleApprover(); Approver videoApprover = new VideoApprover(); Course course = new Course(); course.setName("Java設計模式"); course.setArticle("Java設計模式的手記"); course.setVideo("Java設計模式的視頻"); articleApprover.setNextApprover(videoApprover); articleApprover.deploy(course); } } =======輸出====== Java設計模式含有手記,批準 Java設計模式含有視頻,批準 // 將 course.setVideo("Java設計模式的視頻"); 注釋后,打印結果: Java設計模式含有手記,批準 Java設計模式不含有視頻,不批準,流程結束
UML

說明:其實類圖也很簡單,兩個 Approver 類繼承了其抽象類,Course 是課程主題,最重要的方法就是抽象類 Approver,責任鏈的核心就是 Approver 類里面包含一個自己同樣類型的對象,一般設為 protected,用于子類繼承。
源碼中的應用
- javax.servlet.Filter:重點看它的doFilter方法,看看它有個傳參FilterChain,隨便找一個它下面的實現類MockFilterChain,可以看到它的doFilter方法里面調用了下一個Filter的doFilter方法。
public interface Filter { void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy(); } public interface FilterChain { void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException; } public class MockFilterChain implements FilterChain { private final List<Filter> filters; ... public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { Assert.notNull(request, "Request must not be null"); Assert.notNull(response, "Response must not be null"); if (this.request != null) { throw new IllegalStateException("This FilterChain has already been called!"); } else { if (this.iterator == null) { this.iterator = this.filters.iterator(); } if (this.iterator.hasNext()) { Filter nextFilter = (Filter)this.iterator.next(); nextFilter.doFilter(request, response, this); } this.request = request; this.response = response; } } ... }
- 在 SpringSecurity 中所有的過濾器形成的調用鏈就是用的是責任鏈模式

浙公網安備 33010602011771號