初識設計模式 - 職責鏈模式

来源:https://www.cnblogs.com/fatedeity/archive/2022/11/08/16868497.html
-Advertisement-
Play Games

職責鏈模式是一種與策略模式類似的設計模式,都是使用多個對象去處理同一個請求。不同的是,職責鏈模式針對的一條鏈路上的所有對象,而不是“非此即彼”的關係。 ...


簡介

職責鏈設計模式(Chain Of Responsibility Design Pattern)的定義是,將請求的發送和接收解耦,讓多個接收對象都有機會處理這個請求。

同時,將這些接收對象串成一條鏈,並沿著這條鏈傳遞這個對象,直至鏈上的某個接收對象能夠處理這個請求為止。

職責鏈可以是一條直線、一個環或一個樹形結構,最常見的職責鏈是直線型,即沿著一條單向的鏈來傳遞請求。

典型實現

首先,定義一個抽象處理者 Handler 類,其代碼示例如下:

public abstract class Handler {
    // 維持對下一個處理者的引用
    protected Handler successor;

    public void setHandler(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(String Request);
}

然後,定義一個具體處理者 ConcreteHandler 子類,其代碼示例如下:

public class ConcreteHandler extends Handler {
    public void handleRequest(String request) {
        // 處理請求或者轉發請求
        this.successor.handleRequest(request);
        // 執行完當前處理方法後,可以執行下一個處理者的處理,完成鏈路迴圈
    }
}

對於客戶端而言,只需要知道第一個具體處理者是誰即可,無需關心後續的其他處理者。這就像是操作鏈表一樣,知道鏈表的頭結點即可訪問鏈表的所有結點。

分類

根據處理者對象的行為,職責鏈模式可以分為純的職責鏈模式和不純的職責鏈模式。

純的職責鏈模式

一個純的職責鏈模式要求一個具體處理者對象只能在兩種行為中選擇一個:要麼承擔全部責任,要麼將責任推給下家。

同時,純的職責鏈模式要求一個請求必須被某一個具體處理者對象所接受,不能出現某個請求未被處理者對象接收的情形。

不純的職責鏈模式

不純的職責鏈模式是與純的職責鏈模式相對的一種模式。

在一個不純的職責鏈模式中,允許某個請求被具體處理者部分處理後還能向下傳遞,或者一個具體處理者處理完某個請求後其後繼處理者可以繼續處理該對象,而且同一個請求可以最終不被任何處理者對象所接收。

總結

優點

職責鏈模式的主要優點如下:

  • 將發送者和接收者解耦,客戶端無需知道請求被哪一個對象處理
  • 當工作流程發生變化,可以動態地改變鏈內的成員或調動它們的次序,也可動態的新增或刪除職責
  • 通過鏈式結構串聯處理者,可以根據需要增加新的處理類,符合開閉原則
  • 純的職責鏈模式明確了各類的職責範圍,符合類的單一職責原則

缺點

職責鏈模式的主要缺點如下:

  • 由於請求沒有一個明確的處理者,不能保證請求一定會被處理
  • 對於較長的職責鏈,請求的處理涉及到多個處理對象,系統性能將受到一定影響
  • 職責鏈的建立要靠客戶端來保證,增加了客戶端的複雜性,建鏈不當可能造成迴圈引用

適用場景

職責鏈模式的適用場景如下:

  • 多個對象可以處理一個請求,但具體由哪一個對象處理在運行時自動確定
  • 需要在不明確指定請求處理者的情況下,向多個處理者中的一個提交請求
  • 動態地指定一組處理者,或者改變鏈中處理者之間的次序

源碼

在 JDK 中 java.util.logging.Logger 記錄日誌有可能有多個不同的 Handler 處理器,如果使用這些 Handler 處理器就是一種職責鏈模式的運用。

如下是源碼部分:

public void log(LogRecord record) {
    if (!isLoggable(record.getLevel())) {
        return;
    }
    Filter theFilter = config.filter;
    if (theFilter != null && !theFilter.isLoggable(record)) {
        return;
    }

    Logger logger = this;
    while (logger != null) {
        final Handler[] loggerHandlers = isSystemLogger
            ? logger.accessCheckedHandlers()
            : logger.getHandlers();

        for (Handler handler : loggerHandlers) {
            handler.publish(record);
        }

        final boolean useParentHdls = isSystemLogger
            ? logger.config.useParentHandlers
            : logger.getUseParentHandlers();

        if (!useParentHdls) {
            break;
        }

        logger = isSystemLogger ? logger.parent : logger.getParent();
    }
}

首發於翔仔的個人博客,點擊查看更多。


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

-Advertisement-
Play Games
更多相關文章
  • 1、什麼是CSS Cascading Style Sheet 級聯樣式表。 表現HTML或XHTML文件樣式的電腦語言。 包括對字體、顏色、邊距、高度、寬度、背景圖片、網頁定位等設定。 2、CSS的發展史 CSS1.0 讀者可以從其他地方去使用自己喜歡的設計樣式去繼承性地使用樣式; CSS2.0 ...
  • 虛擬DOM就是用JS來模擬DOM結構的,它並不是真正的DOM。 為什麼使用虛擬DOM? 用傳統的方式去操作DOM的時候,瀏覽器會從構建DOM樹開始,從頭到尾執行一遍流程。簡單來說,就是會觸發重排與重繪。 比如說,在一次操作中,需要更新10個DOM節點。 理想是一次性構建完成DOM樹,但是瀏覽器並不會 ...
  • 一、事件委派 1.理解DOM事件流 事件流描述的是從頁面中接收事件的順序。事件發生時會在元素節點之間按照特定的順序傳播,這個傳播過程即DOM事件流。 DOM事件流分為三個階段: 捕獲階段:從上往下 當前目標階段 冒泡階段:從下往上 事件流如下圖所示: 註意事項: JavaScript代碼中只能執行捕 ...
  • 一.商品列表 1.1 獲取數據 首先能夠進入商品列表的途徑 傳的數據有 瞭解了這個之後就可以開始了,先創建分支 創建編譯模式,並分配初試數據 這個時候就可以獲取數據了 需要的數據 所以在發起請求之前需要整理一下數據,先定義數據 整理數據發起請求 1.2 渲染頁面 ==註意我們可以去定義一個預設的圖片 ...
  • 本文主要記錄 Vue.js 中的 router 管理,涉及如何使用路由實現單頁面應用(SPA)的組件切換,以及路由的一些 API 操作。 ...
  • 1、表單語法 method: 規定如何發送表單數據常用值:get post 在實際網頁開發中通常採用post方式提交表單數據 action: 表示向何處發送表單數據 <form method="post" action="result.html"> <p>名字:<input name="name" ...
  • 1、列表 無序列表和定義列表在網頁製作中應用非常廣泛 什麼是列表: 列表就是信息資源的一種展示形式。它可以使信息結構化和條理化,並以列表的樣式顯示出來,以便瀏覽者能更快捷地獲得相應的信息。 無序列表 <!--ul 聲明無序列表--> <ul> <!--li 聲明列表項--> <li>語文</li> ...
  • 面向對象之魔法方法 一、魔法方法的概念 ​ 定義在類中的雙下方法都可以稱為魔法方法 ​ 不需要人為調用,在特定的條件下會自動觸發,並運行 ​ 類似於__ init__, 當我在使用類產生對象時,會自動觸發 class Foo: # 雙下init就是魔法方法的一種 def __init__(self, ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...