前言
前面的文章咱們通過表驅動法、策略模式兩種方法替換掉JAVA代碼裏的if...else和switch...case,今天繼續介紹第三種方法:責任鏈設計模式。在WEB應用中,大名鼎鼎的filter鏈就是責任鏈模式的具體實現。在筆者一個實際項目中就用到責任鏈模式,來看看吧。
場景
所有移動端app開發,都會面臨一個問題:升級!後臺在開發升級接口時,會判斷很多邏輯,比如版本是否在升級的範圍內、操作系統是否符合、內存、芯片類型、地區、根據ip灰度升級等,以上任何一個不符合就不升級。
還有一種場景,視頻播放鑑權。比如愛奇藝、優酷、騰訊等公司的視頻播放需要鑑權的,比如判斷視頻是否收費、判斷該地域是否能播放、如果視頻支持4K當前設備是否支持等。
以上兩種場景很多人,拿到需求第一步肯定想到if...else判斷。比如下面代碼:
//升級判斷
public boolean upgrade() {
try {
if (!版本在範圍內) {
return false;
}
if(!操作系統符合){
return false;
}
...
} catch (Exception e) {
log.error("異常發生,messge=" + msg, e);
}
}
//播放鑑權
public boolean update() {
try {
if (視頻收費,用戶不是vip) {
return false;
}
if(視頻是4K,設備不支持){
return false;
}
...
} catch (Exception e) {
log.error("異常發生,messge=" + msg, e);
}
}
以上代碼,會存在大量的if...else代碼,最重要的是如果新增判斷怎麼辦?需要修改這個類,增加新的if判斷,這就不符合JAVA的對修改關閉原則,以上問題都是典型的責任鏈模式解決方案,責任鏈模式對擴展開放原則,新增加判斷只需要增加類即可,不修改原代碼。
責任鏈模式
定義:避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,並且沿着這條鏈傳遞請求,直到有對象處理它爲止。職責鏈模式是一種對象行爲型模式。職責鏈模式結構如圖所示:
在職責鏈模式結構圖中包含如下幾個角色:
● Handler(抽象處理者):它定義了一個處理請求的接口,一般設計爲抽象類,由於不同的具體處理者處理請求的方式不同,因此在其中定義了抽象請求處理方法。因爲每一個處理者的下家還是一個處理者,因此在抽象處理者中定義了一個抽象處理者類型的對象(如結構圖中的successor),作爲其對下家的引用。通過該引用,處理者可以連成一條鏈。
● ConcreteHandler(具體處理者):它是抽象處理者的子類,可以處理用戶請求,在具體處理者類中實現了抽象處理者中定義的抽象請求處理方法,在處理請求之前需要進行判斷,看是否有相應的處理權限,如果可以處理請求就處理它,否則將請求轉發給後繼者;在具體處理者中可以訪問鏈中下一個對象,以便請求的轉發。
具體處理者是抽象處理者的子類,它具有兩大作用:第一是處理請求,不同的具體處理者以不同的形式實現抽象請求處理方法handleRequest();第二是轉發請求,如果該請求超出了當前處理者類的權限,可以將該請求轉發給下家。這樣形成了一個鏈式結構,如下圖所示:
升級接口實現
回到上面的問題,我們如何設計升級這個接口呢?首先,從上面的結構圖看,需要首先創建一個接口AbstractUpgradeCheckHandler:
public abstract class AbstractUpgradeCheckHandler<T1, T2> {
protected AbstractUpgradeCheckHandler handler;
/**
* 設置後續處理器
*
* @param handler
*/
public void setNextHandler(AbstractUpgradeCheckHandler handler) {
this.handler = handler;
}
/**
* 升級檢查邏輯處理
*
* @param request 請求參數信息
* @param upInfo 存在的版本升級信息
* @return
*/
public abstract boolean check(T1 request, T2 upInfo);
}
具體的子handler都實現這個接口AbstractUpgradeCheckHandler,例如
VerNoCheckHandler、OpCheckHandler代碼如下:
@Order(1)
@Component
public class VerNoCheckHandler extends AbstractUpgradeCheckHandler<Request, UpdateInfo> {
@Override
public boolean check(Request request, UpgradeInfo upgradeInfo) {
//版本處理邏輯
}
}
@Order(2)
@Component
public class OpCheckHandler extends AbstractUpgradeCheckHandler<Request, UpdateInfo> {
@Override
public boolean check(Request request, UpgradeInfo upgradeInfo) {
//操作系統安保處理邏輯
}
}
Handler鏈工廠類:UpgradeCheckHandlerFactory:
@Component
public class UpgradeCheckHandlerFactory {
@Autowired
private List<AbstractUpgradeCheckHandler<Request, UpgradeInfo>> upgradeCheckHandlers;
private AbstractUpgradeCheckHandler headHandler;
public AbstractUpgradeCheckHandler createHandlerChain() {
if(headHandler != null)
return headHandler;
AbstractUpgradeCheckHandler preHandler = null;
for(AbstractUpgradeCheckHandler handler : upgradeCheckHandlers) {
if(preHandler != null)
preHandler.setNextHandler(handler);
else
headHandler = handler;
preHandler = handler;
}
return headHandler;
}
}
實際調用如下,
AbstractUpgradeCheckHandler<Request, UpgradeInfo> upgradeCheckHandler = upgradeCheckHandlerFactory
.createHandlerChain();
if (upgradeCheckHandler.check(request, upgradeInfo)) {
//升級
} else {
//不升級
}
即使,後續新增需求,比如增加按照升級時間來進行判斷,只需要新建一個UpgradeTimeCheckHandler加入到處理鏈裏就OK了,這就是前面說的對擴展開放。
至此,如何在JAVA編程中幹掉if/else、switch...case三篇完結了,希望你能有所收穫。
關注公衆號:JAVA取經之旅