目錄
Java實作責任鏈設計模式如下:
责任链模式的优缺点
生活中的案例 " >生活中的案例
请假流程的代码实现 " >请假流程的代码实现
大佬們是如何使用的 " >大佬們是如何使用的
首頁 Java java教程 三國演義:責任鏈模式

三國演義:責任鏈模式

Aug 28, 2023 pm 03:16 PM
責任鏈模式

大家好,今天我要跟大家分享設計模式中的責任鏈模式。用貼切的生活故事,以及真實專案場景來講設計模式,最後用一句話來總結這個設計模式。

故事

前兩天,沒事又刷了一遍三國演義,看到關羽身在曹營心在漢,聽說劉備在袁紹那裡,然後就上演了「過五關,斬六將」。

三國演義:責任鏈模式

關羽過五關斬六將主要內容:

  • 第一關,東嶺關,斬守將孔秀。

    東嶺關,守關將名叫孔秀,本是黃巾餘黨,歸降曹操之後,帶著五百人奉命防守東嶺關。關羽車隊從關前通過時,孔秀索要通關文牒,與關羽發生衝突,只有一回合,就被關羽斬殺。

  • 第二關,洛陽關,孟坦和韓福。

    關羽過了東嶺關,在要過洛陽時,韓福、孟坦用鹿角攔住道路。先是孟坦挑戰,與關羽說翻,交手不敵,孟坦撥馬回跑,引關公來追,這樣韓福就可以在後面射箭擒拿關公,可誰想到關公赤兔馬快,從後面趕上孟坦,一刀就把孟坦劈了。韓福慌得射了一箭,中關公左臂,關公忍住箭傷,也衝過鹿角,一刀斬殺韓福,於是過洛陽。

  • 第三關,汜水關,卞喜。

    在得知關羽過關斬將,東嶺關孔秀、洛陽韓福、孟坦都被殺害,卞喜自思難以抵擋關公。於是就假意迎接關公,在鎮國寺安排下刀斧手,準備伺機殺死關公。幸虧有鎮國寺老方丈普淨給警示,關公這才察覺出陰謀,與卞喜鬧翻,一刀斬殺卞喜,於是關公過汜水關。

  • 第四關,王植。

    這王植是韓福的親家,聽說韓福被關公殺死,十分憤怒,於是就要為韓福報仇。在關公到達滎陽時,王植在館驛設宴,宴請關公和二位皇嫂。卻是暗中派從事胡班放火,想要燒死關公。但胡班因關公給父親胡華帶信的緣故,向關羽告了密。關羽和二位皇嫂得以提前逃離館驛,胡班卻假意放火,迷惑王植。不過王植後來察覺,殺了胡班,來追關羽時,被關羽斬殺,於是關公過滎陽。

  • 第五關,黃河渡口,秦琪。

    這秦琪不僅是夏侯惇的愛將,更是老將軍蔡陽的外甥,奉命守衛黃河渡口,盤查過往船隻。關公到黃河渡口時,要找船隻渡河,被秦琪攔住,秦琪不但不放關公等人渡河,反而口出狂言,終於激怒關公,被關公斬殺

#這就是關羽過五關斬六將的全部過程。

這個故事情節讓我想起了一個設計模式:責任鏈模式

其實,我們生活中也有著非常多的責任鏈模式。例如:基本上每個公司都有自己的OA系統,主要是員工基本資料、請假、調休、報銷等功能。如果,我有事需要請假兩天,於是登入OA系統,發起請假審核。

由於,對於請假時間的長短公司有以下規定:

小於等於半天,審批環節:專案負責人

大於半天,小於等於1天的,審批環節:專案負責人技術總監

超過1天,審批環節:專案負責人技術總監Boss

可以看得出來,請假流程為專案負責人技術總監Boss。

到底什麼是責任鏈設計模式?

什麼是責任鏈模式呢

責任鏈模式英文解釋為:

Avoid coupling the sender of a request to its receiver bygiving more than one object a chance to handle the request.Chainthe receiving objects and pass the request along the chain until anobject handv# it.

責任鏈模式(Chain of Responsibility Pattern)將鏈中每個節點都看作一個對象,每個節點處理的請求都不同,且內部自動維護下一個節點對象。當一個請求從鍊式的首端發出時,會沿著責任鏈預設的路徑依序傳遞到每一個節點對象,直到被鏈中的某個對象處理為止,屬於
行為型設計模式

責任鏈模式通用程式碼

Java實作責任鏈設計模式如下:

public abstract class Handler {
        protected Handler nextHandler = null;
        public abstract void handle();
        public Handler getNextHandler() {
            return nextHandler;
        }
        public void setNextHandler(Handler nextHandler) {
            this.nextHandler = nextHandler;
        }
}

public class HandlerA extends Handler{
        @Override
        public void handle() {
            if(nextHandler == null){
                System.out.println("HandlerA handle ...");
            }else{
                nextHandler.handle();
            }
        }
}

public class HandlerB extends Handler{
        @Override
        public void handle() {
            if(nextHandler == null){
                System.out.println("HandlerB handle ...");
            }else{
                nextHandler.handle();
            }
        }
}

public class HandlerC extends Handler{
    @Override
    public void handle() {
        if(getNextHandler() == null){
            System.out.println("HandlerC handle ...");
        }else{
            getNextHandler().handle();
        }
    }
}
//测试
public class  Client{
    public static void main(String[] args) {
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        handlerA.setNextHandler(handlerB);
        handlerA.handle();
    }
}
登入後複製

執行結果:

HandlerC handle ...
登入後複製

從上面程式碼,我們可以畫出UML圖:

三國演義:責任鏈模式


#從UML圖中,我們又可以看出,責任鏈模式中有兩個非常重要的角色:

(1)、抽象處理者角色(Handler)

#定義處理請求的介面。介面可以也可以給出一個方法來設定和傳回對下個物件引用。這個角色通常由一個Java抽象類別或Java介面實作。

(2)、具體處理者角色(HandlerA、HandlerB、HandlerC)

具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下個物件。由於具體處理者持有對下家的引用。

责任链模式的优缺点

  • 优点:请求和处理分开,两者解耦,提供系统的灵活性。
  • 缺点:性能能问,一个链非常长的时候,非常耗时。因为我们避免建立很长的链。

生活中的案例

在日常生活中,责任链模式是比较常见的。我们平时处理工作中的一些事务,往往是各部门协同合作来完成某一个任务的。而每个部门都有各自的职责,因此,很多时候事情完成一半,便会转交到下一个部门,直到所有部门都审批通过,事情才能完成。

责任链模式主要解耦了请求与处理,客户只需将请求发送到链上即可,不需要关心请求的具体内容和处理细节,请求会自动进行传递,直至有节点对象进行处理。

责任链模式主要适用于以下应用场景:

  • 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交请求。
  • 可动态指定一组对象处理请求。

请假流程的代码实现

下面我们来对,前面的案例:OA上请假流程做一个Java代码的实现。

抽象处理者:领导类

public abstract class Leader {
    private Leader next;
    public void setNext(Leader next) {
        this.next = next;
    }
    public Leader getNext() {
        return next;
    }
    //处理请求的方法
    public abstract void handleRequest(double LeaveDays);
}
登入後複製

项目负责人

public class ProjectLeader extends Leader {
    @Override
    public void handleRequest(double LeaveDays) {
        if (LeaveDays <= 0.5) {
            System.out.println("项目负责人批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}
登入後複製

技术总监

public class TechnicalDirectorLeader extends Leader {

    @Override
    public void handleRequest(double LeaveDays) {
        if (LeaveDays <= 1) {
            System.out.println("技术总监批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}
登入後複製

Boss

public class BossLeader extends Leader {
    @Override
    public void handleRequest(double LeaveDays) {
        if (LeaveDays >= 2 && LeaveDays <= 30) {
            System.out.println("Boss批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}
登入後複製

发起审批

public class LeaveApproval {
    public static void main(String[] args) {
        //组装责任链
        Leader projectLeader = new ProjectLeader();
        Leader technicalDirectorLeader = new TechnicalDirectorLeader();
        Leader bossLeader = new BossLeader();

        projectLeader.setNext(technicalDirectorLeader);
        technicalDirectorLeader.setNext(bossLeader);

        //请假两天,提交请假流程,开启审批环节,
        projectLeader.handleRequest(2);
    }
}
登入後複製

审批结果

Boss批准您请假2.0天。
登入後複製

如果请假天数是31天,审批结果

请假天数太多,没有人批准该假条!
登入後複製

整个请假流程为:

三國演義:責任鏈模式


把這張流程圖改成縱向:

三國演義:責任鏈模式


就這麼一環套一環的,使用上面兩個範例和兩張圖來理解責任鏈模式是不是就更輕鬆了?

自己吹牛逼,沒什麼用,下面來看看大神們是怎麼使用責任鏈模式的。

大佬們是如何使用的

在Spring、Mybatis等框架中,都用使用到責任鏈模式,下面先來看在Spring中是如何使用的。

在Spring MVC中的org.springframework.web.servlet.DispatcherServlet類別中:

三國演義:責任鏈模式

#

getHandler 方法的处理使用到了责任链模式,handlerMappings是之前 Spring 容器初始化好的,通过遍历 handlerMappings查找与request匹配的 Handler, 这里返回 HandlerExecutionChain 对象。这个 HandlerExecutionChain对象到后面执行的时候再分析为什么返回的是这样一个对象。

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
 if (this.handlerMappings != null) {
  for (HandlerMapping mapping : this.handlerMappings) {
   HandlerExecutionChain handler = mapping.getHandler(request);
   if (handler != null) {
    return handler;
   }
  }
 }
 return null;
}
登入後複製

以上便是责任链模式在Spring的具体使用

总结

本文通过关二爷的过五关斩六将和OA系统中的请假审批流程,完美的解释了责任链设计模式。

以上是三國演義:責任鏈模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1323
25
PHP教程
1272
29
C# 教程
1251
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

See all articles