如何在JAVA編程中幹掉if/else、switch/case(三)

前言

前面的文章咱們通過表驅動法、策略模式兩種方法替換掉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)@Componentpublic class VerNoCheckHandler extends AbstractUpgradeCheckHandler<Request, UpdateInfo> {  @Override  public boolean check(Request request, UpgradeInfo upgradeInfo) {      //版本處理邏輯  }}
@Order(2)@Componentpublic class OpCheckHandler extends AbstractUpgradeCheckHandler<Request, UpdateInfo> {  @Override  public boolean check(Request request, UpgradeInfo upgradeInfo) {      //操作系統安保處理邏輯  }}

 

Handler鏈工廠類:UpgradeCheckHandlerFactory:

@Componentpublic 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取經之旅

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章