首頁  >  文章  >  Java  >  三國演義:責任鏈模式

三國演義:責任鏈模式

Java后端技术全栈
Java后端技术全栈轉載
2023-08-28 15:16:25933瀏覽

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

故事

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

三國演義:責任鏈模式

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

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

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

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

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

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

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

  • 第四關,王植。

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

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

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

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

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

其實,我們生活中也有著非常多的責任鏈模式。例如:基本上每個公司都有自己的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中文網其他相關文章!

陳述:
本文轉載於:Java后端技术全栈。如有侵權,請聯絡admin@php.cn刪除