設(shè)計(jì)模式學(xué)習(xí)筆記(10)職責(zé)鏈

本文實(shí)例代碼:https://github.com/JamesZBL/java_design_patterns

職責(zé)鏈(Chain of Responsibility 亦譯作 “責(zé)任鏈”)模式中,行為型模式的一種。它的具體特征是,幾乎每個(gè)行為的實(shí)現(xiàn)者都持有職責(zé)鏈中下一個(gè)行為實(shí)現(xiàn)者的引用,在一個(gè)實(shí)現(xiàn)者無(wú)法完成指派給它的職責(zé)的時(shí)候,它就會(huì)將這一職責(zé)的請(qǐng)求傳遞給下一個(gè)實(shí)現(xiàn)者,多個(gè)傳遞關(guān)系就構(gòu)成了一條職責(zé)鏈。

實(shí)例

在一場(chǎng)海上演習(xí)中,作戰(zhàn)指揮官負(fù)責(zé)把控全局,指揮協(xié)調(diào)艦隊(duì)的各部分。指揮官發(fā)出指揮命令后,命令在各部門傳遞執(zhí)行的過(guò)程就是一條職責(zé)鏈。比如,命令全體炮手做好開炮的準(zhǔn)備,職責(zé)鏈就是這樣的:指揮官->艦長(zhǎng)->槍炮長(zhǎng)->炮手,用序列圖表示就是這樣的:

2018-04-27_135628.png

按照 OOP 的慣例,我們又要開始抽象了,將責(zé)任鏈上的傳遞的消息進(jìn)行抽象,形成一個(gè) Request 類。指揮官會(huì)發(fā)布一系列類型的命令,包括行進(jìn)、停止和射擊,每個(gè)命令還包括一些其他的描述,比如命令的具體參數(shù)等。

Request.java


public class Request {

  private boolean isHandled;

  private final String description;

  private final RequestType type;

  protected Request(String description, RequestType type) {

    this.description = description;

    this.type = type;

  }

  public boolean isHandled() {

    return isHandled;

  }

  public void setHandled(boolean handled) {

    isHandled = handled;

  }

  public String getDescription() {

    return description;

  }

  public RequestType getType() {

    return type;

  }

  public void markRequest() {

    setHandled(true);

  }

  @Override

  public String toString() {

    return getDescription();

  }

  public enum RequestType {

    // 射擊

    SHOOTING,

    // 航行

    SAILING,

    // 待命

    AWAIT_ORDERS

  }

}

同樣,職責(zé)鏈上每個(gè)節(jié)點(diǎn)的類都應(yīng)當(dāng)至少實(shí)現(xiàn)同一個(gè)命令處理接口,這個(gè)接口只有一個(gè)方法即 “處理請(qǐng)求”,這里就是根據(jù)上一級(jí)領(lǐng)導(dǎo)的命令作出具體的動(dòng)作,這里用抽象類來(lái)實(shí)現(xiàn):

RequestHandler.java


public abstract class RequestHandler {

  private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);

  private RequestHandler next;

  public RequestHandler(RequestHandler next) {

    this.next = next;

  }

  public void handleRequest(Request request) {

    if (null != next) {

      next.handleRequest(request);

    }

  }

  @Override

  public abstract String toString();

  protected void printHandleMessage(Request request) {

    LOGGER.info("{}處理消息中,消息內(nèi)容為:{}", this, request);

  }

}

那么,這條職責(zé)鏈由誰(shuí)來(lái)創(chuàng)建呢?如果這只隊(duì)伍是指揮官組織起來(lái)的,那么當(dāng)然要由指揮官來(lái)創(chuàng)建了,那么就有了這個(gè)指揮官類:

Commander.java


public class Commander {

  private RequestHandler chain;

  public Commander() {

    createChain();

  }

  private void createChain() {

    chain = new Captain(new Gunny(new Gunner(null)));

  }

  public void handleRequest(Request request) {

    chain.handleRequest(request);

  }

}

指揮官通過(guò)三種級(jí)別的成員的構(gòu)造方法,構(gòu)造出一條完整的職責(zé)鏈,然后將命令發(fā)送給鏈上的第一個(gè)節(jié)點(diǎn),那么這條命令就會(huì)逐級(jí)傳遞下去,最終被執(zhí)行了。

App.java


public class Application {

  public static void main(String[] args) {

    Commander commander = new Commander();

    commander.handleRequest(new Request("正常航行", Request.RequestType.SAILING));

    commander.handleRequest(new Request("原地待命", Request.RequestType.AWAIT_ORDERS));

    commander.handleRequest(new Request("發(fā)射驅(qū)逐導(dǎo)彈", Request.RequestType.SHOOTING));

  }

}

總結(jié)

職責(zé)鏈模式在現(xiàn)實(shí)世界中的應(yīng)用:

  • Tomcat 服務(wù)器對(duì)編碼的處理

  • Spring MVC 的攔截器

  • Servlet 的 Filter

客戶端發(fā)送給服務(wù)器的請(qǐng)求由 Filter(過(guò)濾器)進(jìn)行預(yù)先處理,多個(gè)不同功能的 Filter 構(gòu)成一條 FilterChian,請(qǐng)求經(jīng)過(guò)這條 FilterChian 處理后最終到達(dá) Servlet,在這里被最終處理。

職責(zé)鏈模式的側(cè)重點(diǎn)在單個(gè)環(huán)節(jié)上,它不過(guò)多的關(guān)注其他行為實(shí)現(xiàn)者的特征。職責(zé)鏈上的每個(gè)節(jié)點(diǎn)都至少持有下一個(gè)實(shí)現(xiàn)者的引用,和數(shù)據(jù)結(jié)構(gòu)中的 “鏈表” 類似,鏈上的消息具有單項(xiàng)傳遞性,這個(gè)節(jié)點(diǎn)任務(wù)完成后將消息發(fā)送給鏈上的下一個(gè)節(jié)點(diǎn),依次傳遞下去,最終構(gòu)成一條職責(zé)鏈。

個(gè)人博客同步更新,獲取更多技術(shù)分享請(qǐng)關(guān)注:鄭保樂(lè)的博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,968評(píng)論 1 92
  • 參考資料:菜鳥教程之設(shè)計(jì)模式 設(shè)計(jì)模式概述 設(shè)計(jì)模式(Design pattern)代表了最佳的實(shí)踐,通常被有經(jīng)驗(yàn)...
    Steven1997閱讀 1,279評(píng)論 1 12
  • 漸蒼茫曙色上梢頭,心緒作閑愁。看大雪節(jié)氣,鵲鳴冷樹,晨風(fēng)颼颼。是處枯枝瘦葉,湖水凍殘舟。獨(dú)留蘆葦蕩,無(wú)語(yǔ)凝眸。 我...
    逸塵居士閱讀 245評(píng)論 0 0
  • 我認(rèn)為任何產(chǎn)品都應(yīng)該以解決用戶痛點(diǎn)為根本,而不能以融資為目的。 嘀嗒拼車的創(chuàng)意真的不錯(cuò),解決了乘客覺(jué)得打車貴、擠公...
    立廠三口閱讀 1,179評(píng)論 0 2

友情鏈接更多精彩內(nèi)容