【設計模式】通俗易懂版責任鏈模式
theme: juejin
引入
汽車生產過程中,必然要對汽車的各個部件,比如發動機、變速箱、車身等等進行嚴格的質量檢查,對不合格的部件進行過濾。
過濾檢查汽車部件
一般情況下,我們這樣寫就能實現了:
```java public class Client { public static void main(String[] args) { Client client = new Client();
Request req = new Request();
req.setReqMsg("檢查發動機,變速箱,車身有沒有問題");
if (req.getReqMsg().contains("車身")) {
client.doCheckCarbody();
}
if (req.getReqMsg().contains("發動機")) {
client.doCheckEngine();
}
if (req.getReqMsg().contains("變速箱")) {
client.doCheckGearbox();
}
if (req.getReqMsg().contains("xxx")) {
// do something
}
}
public void doCheckEngine () {
System.out.println("------檢查了發動機------");
}
public void doCheckCarbody () {
System.out.println("------檢查了車身-------");
}
public void doCheckGearbox () {
System.out.println("------檢查了變速箱-----");
}
}
class Request { private String reqMsg;
public String getReqMsg() {
return reqMsg;
}
public void setReqMsg(String reqMsg) {
this.reqMsg = reqMsg;
}
} ``` but,看到
java
if (req.getReqMsg().contains("xxx")) {
// do something
}
這個了嗎?這意味著檢查的東西增多,if
語句也就變多了(好熟悉的程式碼,哈哈)
如何幹掉臃腫的if
,優雅的執行汽車部件檢查?
針對上面的程式碼,如果哪天哪個部件獲得免檢了,不需要檢查了,還得去掉某一個if
分支,這時候你就恨不得把所有程式碼都重構了。。。
面向物件有一個詞叫 封裝變化 ,也就是說 哪部分要變化,就封裝哪部分 ,我們可以對處理汽車部件的部分進行封裝。
程式碼如下: ```java public class Client { public static void main(String[] args) { Request req = new Request(); req.setReqMsg("檢查發動機,變速箱,車身有沒有問題");
List<Filter> filters = new ArrayList<>();
filters.add(new CarbodyFilter());
filters.add(new GearboxFilter());
filters.add(new EngineFilter());
for (Filter f : filters) {
f.doFilter(req);
}
}
}
class Request { private String reqMsg;
public String getReqMsg() {
return reqMsg;
}
public void setReqMsg(String reqMsg) {
this.reqMsg = reqMsg;
}
}
interface Filter { boolean doFilter(Request request); }
class EngineFilter implements Filter { @Override public boolean doFilter(Request request) { if (request.getReqMsg().contains("發動機")) { System.out.println("------檢查了發動機------"); } return true; } }
class GearboxFilter implements Filter { @Override public boolean doFilter(Request request) { if (request.getReqMsg().contains("變速箱")) { System.out.println("------檢查了變速箱------"); } return true; } }
class CarbodyFilter implements Filter { @Override public boolean doFilter(Request request) { if (request.getReqMsg().contains("車身")) { System.out.println("------檢查了車身------"); } return true; } } ``` 這樣一來,如果要對哪個部件進行檢查,只需要向
java
List<Filter> filters = new ArrayList<>();
filters
裡新增Filter
就行了,這個程式碼是不是稍微有那麼點意思了?
沒有最優雅,只有更優雅
上個版本的程式碼,仍需要在 Client
裡面的 List<Filter>
裡新增需要執行的 Filter
,還是差點意思。
我們來看一下上面描述的場景:
是不是每個 Filter
各司其職,只要把每個 Filter
串起來讓他們內部去執行就好了!
那我們來寫一個 FilterChain
來把他們串起來:
```java
class FilterChain implements Filter {
List
//比較騷的寫法,這樣可以鏈式呼叫
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
//一般寫法
// public void add(Filter filter) { // filters.add(filter); // }
@Override
public boolean doFilter(Request request) {
for (Filter f : filters) {
//任何一環檢查出了問題,均不往下檢查
if (!f.doFilter(request)) {
return false;
}
}
return true;
}
}
``
這裡提一下
FilterChain中的
add`方法,先看一般寫法:
java
public void add(Filter filter) {
filters.add(filter);
}
然後呼叫就得這樣來搞:
java
FilterChain chain = new FilterChain();
chain.add(new EngineFilter());
chain.add(new GearboxFilter());
chain.add(new CarbodyFilter());
chain.doFilter(req);
有一種比較騷的寫法:
java
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
呼叫:
java
FilterChain chain = new FilterChain();
chain.add(new EngineFilter())
.add(new GearboxFilter())
.add(new CarbodyFilter())
.doFilter(req);
咦?我在xx原始碼見過這個寫法!感覺瞬間提升了幾個檔次。
上面的 FilterChain
版本,其實就是 責任鏈模式 !!!
似曾相識的FilterChain
沒錯,如果你開發過Java Web程式,你一定見過這個東西。
比如 Servlet
的 Filter
, Struts
的 Interceptor
, Spring MVC
的 HandlerInterceptor
。它們本質上都是過濾器或者叫攔截器。
我用剛才的場景
模擬了一下Filter
和FilterChain
:
```java public class Client { public static void main(String[] args) { Request request = new Request(); request.reqMsg = "檢查發動機,變速箱,車身有沒有問題"; Response response = new Response(); response.respMsg = "-------response:";
FilterChain chain = new FilterChain();
chain.add(new EngineFilter()).add(new GearboxFilter()).add(new CarbodyFilter());
chain.doFilter(request, response);
System.out.println(response.respMsg);
}
}
class Request { String reqMsg; }
class Response { String respMsg; }
interface Filter { void doFilter(Request request, Response response, FilterChain chain); }
class EngineFilter implements Filter { public void doFilter(Request request, Response response, FilterChain chain) { //先處理request請求 if (request.reqMsg.contains("發動機")) { System.out.println("------EngineFilter 檢查了發動機------"); } //通過鏈條傳遞處理下一個request chain.doFilter(request, response); //處理response response.respMsg += "---執行了EngineFilter過濾器---"; } }
class GearboxFilter implements Filter { public void doFilter(Request request, Response response, FilterChain chain) { if (request.reqMsg.contains("變速箱")) { System.out.println("------GearboxFilter 檢查了變速箱------"); } //通過鏈條傳遞處理下一個request chain.doFilter(request, response); //處理response response.respMsg += "---執行了GearboxFilter過濾器---"; } }
class CarbodyFilter implements Filter { public void doFilter(Request request, Response response, FilterChain chain) { if (request.reqMsg.contains("車身")) { System.out.println("------CarbodyFilter 檢查了車身------"); } //通過鏈條傳遞處理下一個request chain.doFilter(request, response); //處理response response.respMsg += "---執行了CarbodyFilter過濾器---"; } }
class FilterChain {
List
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public void doFilter(Request request, Response response) {
//如果request鏈條執行完了,就不往下傳遞了
if (filterIndex == filters.size()) {
return;
}
Filter f = filters.get(filterIndex);
filterIndex++;
f.doFilter(request, response, this);
}
} ``` 捋一捋:
FilterChain
裡面定義了一個 filterIndex
來控制鏈條順序執行,並且在每個filter的doFilter裡
1. 先處理request
2. 呼叫chain.doFilter(request, response)傳遞鏈條
3. 處理response
看下執行結果:
這些框架的過濾器、攔截器使用的也是 責任鏈模式 。
小結
- 責任鏈模式 (Chain of Responsibility)是一種 處理請求 的模式,它讓多個處理器都有機會處理該請求,直到其中某個處理成功為止。責任鏈模式把多個處理器串成鏈,然後讓請求在鏈上傳遞。
- 責任鏈模式在新增新的處理類或者排列處理請求的順序上非常容易。
- 攔截、預處理請求等場景下經常會用到責任鏈模式。
暗示自己:好好學習設計模式,咱也能寫出優秀的程式碼!!!
以上。
點個贊再走吧~
我正在參與掘金技術社群創作者簽約計劃招募活動,點選連結報名投稿。
- Java最強大的技術之一:反射
- 【設計模式】通過一個簡單的案例理解-訪問者模式(Visitor Pattern)
- 【設計模式】模板模式,學會它咱也寫出優雅健壯的程式碼!
- 【設計模式】通俗易懂版責任鏈模式
- 【設計模式】代理模式那些事兒:靜態代理,動態代理,JDK的動態代理,cglib,Spring AOP
- 萬字長文 | Spring Cloud Alibaba元件之Nacos實戰及Nacos客戶端服務註冊原始碼解析
- 【設計模式】只需體驗三分鐘,你就會跟我一樣瞭解Facade和Mediator模式
- 【設計模式】工廠系列-FactoryMethod,AbstractFactory,Spring IOC
- 【資料結構】| 連結串列資料結構及其簡單玩法解析
- 系統架構演進與Spring Cloud Alibaba簡介
- 【FastDFS】一文學會一個分散式檔案系統!
- 【MySQL 8】MySQL 5.7都即將停只維護了,是時候學習一波MySQL 8了!
- 使用Rancher部署管理K8S叢集,真香!
- 玩轉Docker映象倉庫-Docker Registry及Harbor
- 【設計模式】各個擊破單例模式的8種寫法
- 容器化技術之Docker-從入地到上天
- 【RocketMQ】RocketMQ叢集,RocketMQ-on-DLedger可容災叢集
- 【RocketMQ】基於RocketMQ的分散式事務
- 【RocketMQ】近距離感受RocketMQ如何收發訊息,有備而來!
- 【RocketMQ】RocketMQ入門之閃電三連鞭:訊息佇列、RocketMQ介紹及安裝使用