《設計模式之禪》學習之 “責任鏈模式”

来源:http://www.cnblogs.com/scharfsinnig/archive/2017/05/07/6820253.html
-Advertisement-
Play Games

本章一開始舉了中國古代對婦女制定的 “三從四德” 的道德規範,形象地將女性在 “未嫁 出嫁 喪父” 三個不同的狀態下請示出門逛街獲得的處理,未嫁的時候,請示父親;出嫁了,請示丈夫;丈夫去世了,請示兒子。責任鏈就是:父親 丈夫 兒子。如果出嫁了,請示父親,會得到什麼結果?答案是:父親告訴他,你該去請示 ...


本章一開始舉了中國古代對婦女制定的 “三從四德” 的道德規範,形象地將女性在 “未嫁-> 出嫁 -> 喪父” 三個不同的狀態下請示出門逛街獲得的處理,未嫁的時候,請示父親;出嫁了,請示丈夫;丈夫去世了,請示兒子。責任鏈就是:父親 -> 丈夫 -> 兒子。如果出嫁了,請示父親,會得到什麼結果?答案是:父親告訴他,你該去請示你的丈夫。讀完還是蠻形象的。
其實,作者給我們闡述了這麼一個場景:一個請求到來的時候,請求方並不知道也不必知道誰去處理請求,責任鏈也不必關心誰發出的請求。請求來了,從第一個處理者開始,如果屬於這一層,就處理。不屬於?分發到下一個節點。下一個不能處理怎麼辦?再下一個。尋找處理者就是遍歷鏈表節點的過程。
為什麼這麼做?這樣做,就避免了請求和處理耦合在一起,代碼也簡潔了很多。
Talk is cheap, show me the code.
先創建一個女性介面:

public interface IWomen {

    // 獲得個人狀態.
    public int getType();

    // 獲得個人請示
    public String getRequest();
}

創建一個古代婦女:

public class Women implements IWomen {

    /**
     * 通過 int 類型的參數來描述婦女的個人狀況.
     * <p/>
     * 1 -> 未出嫁;
     * 2 -> 出嫁;
     * 3 -> 夫死;
     */
    private int type = 0;

    /**
     * 婦女的請示
     */
    private String request = "";

    public Women(int type, String request) {
        this.type = type;

        switch (this.type) {
            case 1:
                this.request = "女兒的請示是: " + request;
                break;
            case 2:
                this.request = "妻子的請求是: " + request;
                break;
            case 3:
                this.request = "母親的請求是: " + request;
        }
    }

    /**
     * 獲取自己的狀態.
     *
     * @return
     */
    public int getType() {
        return this.type;
    }

    /**
     * 獲取婦女的請求.
     *
     * @return
     */
    public String getRequest() {
        return this.request;
    }
}

有處理權的人員介面:

public abstract class Handler {
    public final static int FATHER_LEVEL_REQUEST = 1;
    public final static int HUSBAND_LEVEL_REQUEST = 2;
    public final static int SON_LEVEL_REQUEST = 3;

    /**
     * 能處理的級別
     */
    private int level = 0;

    /**
     * 責任傳遞,下一個責任人是誰
     */
    private Handler nextHandler;

    /**
     * 每個類都要說明一下自己能處理哪些請求
     */
    public Handler(int level) {
        this.level = level;
    }

    /**
     * 處理女性的請求.
     *
     * @param women
     */
    public final void HandleMessage(IWomen women) {
        if (women.getType() == this.level) {
            this.response(women);
        } else {
            if (null != this.nextHandler) {
                this.nextHandler.HandleMessage(women);
            } else {
                // 沒有後續的處理人了.
                System.out.println("\n-------沒有地方請示了,按不同意處理-------\n");
            }
        }
    }

    /**
     * 如果不屬於該類處理的請求,應該將其設置到下一個需要請求的環節.
     *
     * @param handler
     */
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    /**
     * 有請求肯定要有回應
     *
     * @param women
     */
    protected abstract void response(IWomen women);
}

父親類:

public class Father extends Handler {

    public Father() {
        super(Handler.FATHER_LEVEL_REQUEST);
    }

    @Override
    protected void response(IWomen women) {
        System.out.println("\n-------女兒向父親請示-------");
        System.out.println(women.getRequest());
        System.out.println("父親的回答是: 同意\n");
    }
}

丈夫類:

public class Husband extends Handler {

    public Husband() {
        super(Handler.HUSBAND_LEVEL_REQUEST);
    }

    @Override
    protected void response(IWomen women) {
        System.out.println("-------妻子向丈夫請示-------");
        System.out.println(women.getRequest());
        System.out.println("丈夫的答覆是: 同意");
    }
}

兒子類:

public class Son extends Handler {

    public Son() {
        super(Handler.SON_LEVEL_REQUEST);
    }

    @Override
    protected void response(IWomen women) {
        System.out.println("-------母親向兒子請示-------");
        System.out.println(women.getRequest());
        System.out.println("兒子的答覆是: 同意\n");
    }
}

場景類:

public class Client {
    public static void main(String[] args) {
        Random random = new Random();
        ArrayList<IWomen> arrayList = new ArrayList<IWomen>();

        for (int i = 0; i < 5; i++) {
            arrayList.add(new Women(random.nextInt(4), "我要去逛街"));
        }

        // 定義三個請求對象
        Father father = new Father();
        Husband husband = new Husband();
        Son son = new Son();

        father.setNextHandler(husband);
        husband.setNextHandler(son);

        for (IWomen women : arrayList) {
            father.HandleMessage(women);
        }
    }
}

運行結果:

-------母親向兒子請示-------
母親的請求是: 我要去逛街
兒子的答覆是: 同意

-------妻子向丈夫請示-------
妻子的請求是: 我要去逛街
丈夫的答覆是: 同意
-------母親向兒子請示-------
母親的請求是: 我要去逛街
兒子的答覆是: 同意


-------沒有地方請示了,按不同意處理-------

-------妻子向丈夫請示-------
妻子的請求是: 我要去逛街
丈夫的答覆是: 同意

在抽象類 Handler 中,我們設置了級別 level 的參數用來標示子類的等級;定義了 nextHandler 來制定當前節點的下一個處理節點。這樣,每個子類在生成實例對象的時候,通過指定下一個節點,就可以生成責任鏈了。
責任鏈模式的重點是在“鏈”上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,並返回相應的結果。其優點就是將請求和處理分開來了。請求者不需要知道誰將處理這個請求,處理者也不要知道誰發起了這個請求。兩者解耦,提高了系統的靈活性。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 看了好多關於代理的文章,理解和整理一下。 1、代理的基本構成 抽象角色:聲明真實對象和代理對象的共同介面,這樣可在任何使用真實對象的地方都可以使用代理對象。 代理角色:代理對象內部含有真實對象的引用,從而可以在任何時候操作真實對象。代理對象提供一個與真實對象相同的介面,以便可以在任何時候替代真實對象 ...
  • Description Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. Do not allocate ex ...
  • Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. k is a positive integer and is less than or equal t... ...
  • 首先瞭解一下Python的優點: Python為我們提供了非常完善的基礎代碼庫,覆蓋了網路、文件、GUI、資料庫、文本等大量內容,被形象地稱作“內置電池(batteries included)”。用Python開發,許多功能不必從零編寫,直接使用現成的即可。 除了內置的庫外,Python還有大量的第 ...
  • 上篇博客我們聊了《JavaEE開發之SpringBoot工程的創建、運行與配置》,從上篇博客的內容我們不難看出SpringBoot的便捷。本篇博客我們繼續在上篇博客的基礎上來看一下SpringBoot是如何引入和使用MyBatis和Thymeleaf的。在之前的博客中我們提到過Hibernate,今 ...
  • jvm記憶體模型 u 程式計數器 u Java棧(虛擬機棧) u 本地方法棧 u Java堆 u 方法區及其運行時常量池 垃圾回收機制 u 新生代和老年代 u 參數設置 u 垃圾回收(Minor GC 和 Full GC)和回收演算法 u finalize()、減少GC開銷、觸發主GC的條件 u 判斷無 ...
  • HashSet:哈希表是通過使用稱為散列法的機制來存儲信息的,元素並沒有以某種特定順序來存放; LinkedHashSet:以元素插入的順序來維護集合的鏈接表,允許以插入的順序在集合中迭代; TreeSet:提供一個使用樹結構存儲Set介面的實現,對象以升序順序存儲,訪問和遍歷的時間很快。 ...
  • 周末沒出門,熬了兩個夜整理代碼、打磨圖示,給大家奉上本文。敢說最準確,因為:1. 我嚴格對照所畫時序圖的每個步驟,開發了完整的跨域單點登錄範例;2. 所有服務端步驟,都在代碼中逐一標註,跟蹤代碼就能兩相對照,實際的深入理解流程;3. SSO核心在寫Cookie、URL傳參策略,其參與對象多、邏輯分支... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...