1. 程式人生 > >Java設計模式----責任鏈模式

Java設計模式----責任鏈模式

簡述:

    前端時間再看一些類庫的原始碼,發現責任鏈模式的強大之處,尤其是和建造者模式的結合後強大的動態可擴充套件性更是牛逼的一塌糊塗。接下來趕緊了解一下吧!     我們先來了解一下什麼是責任鏈模式:     職責鏈模式(Chain of Responsibility):使多個物件都有機會處理同一個請求,從而避免請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。 應用場景:      為完成同一個請求,如果存在多個請求處理器以及未知請求處理器個數或者請求處理器可動態配置的情況下,可以考慮使用責任鏈模式。如OKHttp的攔截器就是使用的責任鏈模式。

例項UML圖:

               

例項執行流程圖:

           

例項:

    1、例項場景

    在公司內部員工請假一般情況是這樣的:員工在OA系統中提交一封請假郵件,該郵件會自動轉發到你的直接上級領導郵箱裡,如果你的請假的情況特殊的話,該郵件也會轉發到你上級的上級的郵箱,根據請假的情況天數多少,系統會自動轉發相應的責任人的郵箱。我們就以這樣一種場景為例完成一個責任鏈模式的程式碼。為了更清晰的描述這種場景我們規定如下:     ① GroupLeader(組長 ):他能批准的假期為2天,如果請假天數超過2天就將請假郵件自動轉發到組長和經理郵箱。
    ② Manager(經理):他能批准的假期為4天以內,如果請假天數大於4天將該郵件轉發到自動轉發到組長、經理和部門領導的郵箱。     ③ DepartmentHeader(部門領導):他能批准的假期為7天以內,如果大於7天就只批准7天。

    2、例項程式碼

    我們清楚了上面的場景以後就開始定義模型:         ①根據面向物件的思想我們得定義需要用到的物件。OK,為了更加清楚的說明“責任鏈模式的可擴充套件性”問題我這裡採用了建造者模式構造Request物件,“請假”物件Request如下:
/**
 * 類描述:請假物件
 *
 * @author lzy
 */
public class Request {
     private String name;

     private String reason;

     private int days;

     private String groupLeaderInfo;

     private String managerInfo;

     private String departmentHeaderInfo;

     private String customInfo;

     public Request(Builder builder) {
          super();
          this.name = builder.name;
          this.reason = builder.reason;
          this.days = builder.days;
          this.groupLeaderInfo = builder.groupLeaderInfo;
          this.managerInfo = builder.managerInfo;
          this.departmentHeaderInfo = builder.departmentHeaderInfo;
          this.customInfo = builder.customInfo;
     }

     public static class Builder {
          public String name;

          public String reason;

          public int days;

          public String groupLeaderInfo;

          public String managerInfo;

          public String departmentHeaderInfo;

          public String customInfo;

          public Builder() {

          }

          public Builder setName(String name) {
              this.name = name;
              return this;
          }

          public Builder setReason(String reason) {
              this.reason = reason;
              return this;
          }

          public Builder setDays(int days) {
              this.days = days;
              return this;
          }

          public Builder setGroupLeaderInfo(String groupLeaderInfo) {
              this.groupLeaderInfo = groupLeaderInfo;
              return this;
          }

          public Builder setManagerInfo(String managerInfo) {
              this.managerInfo = managerInfo;
              return this;
          }

          public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
              this.departmentHeaderInfo = departmentHeaderInfo;
              return this;
          }

          public Builder setCustomInfo(String customInfo) {
              this.customInfo = customInfo;
              return this;
          }

          public Builder newRequest(Request request) {
              this.name = request.name;
              this.days = request.days;
              this.reason = request.reason;
              if (request.groupLeaderInfo != null
                        && !request.groupLeaderInfo.equals("")) {
                   this.groupLeaderInfo = request.groupLeaderInfo;
              }

              if (request.managerInfo != null && !request.managerInfo.equals("")) {
                   this.managerInfo = request.managerInfo;
              }

              if (request.departmentHeaderInfo != null
                        && !request.departmentHeaderInfo.equals("")) {
                   this.departmentHeaderInfo = request.departmentHeaderInfo;
              }

              if (request.customInfo != null && !request.customInfo.equals("")) {
                   this.customInfo = request.customInfo;
              }
              

              return this;
          }

          public Request build() {
              return new Request(this);
          }
     }

     public String name() {
          return name;
     }

     public String reason() {
          return reason;
     }

     public int days() {
          return days;
     }

     public String groupLeaderInfo() {
          return groupLeaderInfo;
     }

     public String managerInfo() {
          return managerInfo;
     }

     public String departmentHeaderInfo() {
          return departmentHeaderInfo;
     }

     public String customInfo() {
          return customInfo;
     }

     @Override
     public String toString() {
          return "Request [name=" + name + ", reason=" + reason + ", days="
                   + days + ",customInfo=" + customInfo + ", groupLeaderInfo="
                   + groupLeaderInfo + ", managerInfo=" + managerInfo
                   + ", departmentHeaderInfo=" + departmentHeaderInfo + "]";
     }

}
        接下來再定義“批准結果”物件Result:
/**
 * 類描述:結果物件
 *
 * @author lzy
 *
 */
public class Result {
     public boolean isRatify;
     public String info;

     public Result() {

     }

     public Result(boolean isRatify, String info) {
          super();
          this.isRatify = isRatify;
          this.info = info;
     }

     public boolean isRatify() {
          return isRatify;
     }

     public void setRatify(boolean isRatify) {
          this.isRatify = isRatify;
     }

     public String getReason() {
          return info;
     }

     public void setReason(String info) {
          this.info = info;
     }

     @Override
     public String toString() {
          return "Result [isRatify=" + isRatify + ", info=" + info + "]";
     }
}
    ②我們接下來再來定義一個介面,這個介面用於處理Request和獲取請求結果Result。
/**
 * 介面描述:處理請求
 *
 * @author lzy
 *
 */
public interface Ratify {
     // 處理請求
     public Result deal(Chain chain);

     /**
      * 介面描述:對request和Result封裝,用來轉發
      */
     interface Chain {
          // 獲取當前request
          Request request();

          // 轉發request
          Result proceed(Request request);
     }
}
   看到上面的介面,可能會有人迷惑:在介面Ratify中為什麼又定義一個Chain介面呢?其實這個介面是單獨定義還是內部介面沒有太大關係,但是考慮到Chain介面與Ratify介面的關係為提高內聚性就定義為內部介面了。定義Ratify介面是為了處理Request那為什麼還要定義Chain介面呢?這正是責任連結口的精髓之處:轉發功能及可動態擴充套件“責任人”,這個介面中定義了兩個方法一個是request()就是為了獲取request,如果當前Ratify的實現類獲取到request之後發現自己不能處理或者說自己只能處理部分請求,那麼他將自己的那部分能處理的就處理掉,然後重新構建一個或者直接轉發Request給下一個責任人。可能這點說的不容易理解,我舉個例子,在Android與後臺互動中如果使用了Http協議,當然我們可能使用各種Http框架如HttpClient、OKHttp等,我們只需要傳送要請求的引數就直接等待結果了,這個過程中你可能並沒有構建請求頭,那麼框架幫你把這部分工作給做了,它做的工程中如果使用了責任鏈模式的話,它肯定會將Request進行包裝(也就是新增請求頭)成新的Request,我們姑且加他為Request1,如果你又希望Http做本地快取,那麼Request1又會被轉發到並且重新進一步包裝為Request2。總之Chain這個介面就是起到對Request進行重新包裝的並將包裝後的Request進行下一步轉發的作用。如果還不是很明白也沒關係,本例項會演示這一功能機制。     ③上面說Chain是用來對Request重新包裝以及將包裝後的Request進行下一步轉發用的,那我們就具體實現一下:
/**
 * 類描述:實現Chain的真正的包裝Request和轉發功能
 *
 * @author lzy
 *
 */
public class RealChain implements Chain {
     public Request request;
     public List<Ratify> ratifyList;
     public int index;

     /**
      * 構造方法
      *
      * @param ratifyList
      *            Ratify介面的實現類集合
      * @param request
      *            具體的請求Request例項
      * @param index
      *            已經處理過該request的責任人數量
      */
     public RealChain(List<Ratify> ratifyList, Request request, int index) {
          this.ratifyList = ratifyList;
          this.request = request;
          this.index = index;
     }

     /**
      * 方法描述:具體轉發功能
      */
     @Override
     public Result proceed(Request request) {
          Result proceed = null;
          if (ratifyList.size() > index) {
              RealChain realChain = new RealChain(ratifyList, request, index + 1);
              Ratify ratify = ratifyList.get(index);
              proceed = ratify.deal(realChain);
          }

          return proceed;
     }

     /**
      * 方法描述:返回當前Request物件或者返回當前進行包裝後的Request物件
      */
     @Override
     public Request request() {
          return request;
     }

}
    ④ 經過上面幾步我們已經完成了責任鏈模式的核心功能,接下來我們定義幾個相關責任物件:GroupLeader、Manager和DepartmentHeader,並讓他們實現Ratify介面。
/**
 * 組長
 *
 * @author lzy
 *
 */
public class GroupLeader implements Ratify {

     @Override
     public Result deal(Chain chain) {
          Request request = chain.request();
          System.out.println("GroupLeader=====>request:" + request.toString());

          if (request.days() > 1) {
              // 包裝新的Request物件
              Request newRequest = new Request.Builder().newRequest(request)
                        .setManagerInfo(request.name() + "平時表現不錯,而且現在專案也不忙")
                        .build();
              return chain.proceed(newRequest);
          }

          return new Result(true, "GroupLeader:早去早回");
     }
}


/**
 * 經理
 *
 * @author lzy
 *
 */
public class Manager implements Ratify {

     @Override
     public Result deal(Chain chain) {
          Request request = chain.request();
          System.out.println("Manager=====>request:" + request.toString());
          if (request.days() > 3) {
              // 構建新的Request
              Request newRequest = new Request.Builder().newRequest(request)
                        .setManagerInfo(request.name() + "每月的KPI考核還不錯,可以批准")
                        .build();
              return chain.proceed(newRequest);

          }
          return new Result(true, "Manager:早點把事情辦完,專案離不開你");
     }

}

/**
 * 部門領導
 *
 * @author lzy
 *
 */
public class DepartmentHeader implements Ratify {

     @Override
     public Result deal(Chain chain) {
          Request request = chain.request();
          System.out.println("DepartmentHeader=====>request:"
                   + request.toString());
          if (request.days() > 7) {
              return new Result(false, "你這個完全沒必要");
          }
          return new Result(true, "DepartmentHeader:不要著急,把事情處理完再回來!");
     }

}
    到此,責任鏈模式的一個Demo就算是完成了,但為了方便呼叫,我們在寫一個該責任鏈模式的客戶端工具類ChainOfResponsibilityClient 如下:
/**
 * 類描述:責任鏈模模式工具類
 *
 * @author lzy
 *
 */
public class ChainOfResponsibilityClient {
private ArrayList<Ratify> ratifies;

     public ChainOfResponsibilityClient() {
          ratifies = new ArrayList<Ratify>();
     }

     /**
      * 方法描述:為了展示“責任鏈模式”的真正的迷人之處(可擴充套件性),在這裡構造該方法以便新增自定義的“責任人”
      *
      * @param ratify
      */
     public void addRatifys(Ratify ratify) {
          ratifies.add(ratify);
     }

     /**
      * 方法描述:執行請求
      *
      * @param request
      * @return
      */
     public Result execute(Request request) {
          ArrayList<Ratify> arrayList = new ArrayList<Ratify>();
          arrayList.addAll(ratifies);
          arrayList.add(new GroupLeader());
          arrayList.add(new Manager());
          arrayList.add(new DepartmentHeader());

          RealChain realChain = new RealChain(this, arrayList, request, 0);
          return realChain.proceed(request);
     }
    
}
     OK,我們測試一下見證奇蹟吧:
/**
 * 類描述:責任鏈模式測試類
 *
 * @author lzy
 *
 */
public class Main {

     public static void main(String[] args) {

          Request request = new Request.Builder().setName("張三").setDays(5)
                   .setReason("事假").build();
          ChainOfResponsibilityClient client = new ChainOfResponsibilityClient();
          Result result = client.execute(request);

          System.out.println("結果:" + result.toString());
     } 
}
    這個請求是張三請事假5天,按照我們的約定應該請求會到達部門領導手裡,且他看到請求的樣式為:“ [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=張三平時表現不錯,而且現在專案也不忙, managerInfo=張三每月的KPI考核還不錯,可以批准, departmentHeaderInfo=null]”     我們看一下列印的日誌:
GroupLeader=====>request:Request [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
Manager=====>request:Request [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=張三平時表現不錯,而且現在專案也不忙, managerInfo=null, departmentHeaderInfo=null]
DepartmentHeader=====>request:Request [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=張三平時表現不錯,而且現在專案也不忙, managerInfo=張三每月的KPI考核還不錯,可以批准, departmentHeaderInfo=null]
結果:Result [isRatify=true, info=DepartmentHeader:不要著急,把事情處理完再回來!]
    OK,和預期一樣完美。剛開始就提到這個責任鏈模式是可以“動態擴充套件的”,我們驗證一下,首先自定義一個“責任人”(其實也可以叫攔截器):
/**
 * 類描述:自定義“責任人”
 *
 * @author lzy
 *
 */
public class CustomInterceptor implements Ratify {

     @Override
     public Result deal(Chain chain) {
          Request request = chain.request();
          System.out.println("CustomInterceptor=>" + request.toString());
          String reason = request.reason();
          if (reason != null && reason.equals("事假")) {
              Request newRequest = new Request.Builder().newRequest(request)
                        .setCustomInfo(request.name() + "請的是事假,而且很著急,請領導重視一下")
                        .build();
              System.out.println("CustomInterceptor=>轉發請求");
              return chain.proceed(newRequest);
          }
          return new Result(true, "同意請假");
     }

}
    然後在測試類Main.java中呼叫如下:
/**
 * 類描述:責任鏈模式測試類
 *
 * @author lzy
 *
 */
public class Main {

     public static void main(String[] args) {

          Request request = new Request.Builder().setName("張三").setDays(5)
                   .setReason("事假").build();
          ChainOfResponsibilityClient client = new ChainOfResponsibilityClient();
          client.addRatifys(new CustomInterceptor());
          Result result = client.execute(request);

          System.out.println("結果:" + result.toString());
     }

}
    OK,看一下日誌:

      哈哈,責任鏈模式功能之強大還要多用多體會呀!

相關推薦

java 設計模式 -- 責任模式

ddc 結果 fun intercept lock -s xtend print blog 設計模式 – 責任鏈模式 介紹: 責任鏈模式是一種動態行為模式,有多個對象,每一個對象分別擁有其下家的引用。連起來形成一條鏈。待處理對象則傳到此鏈上

我的Java設計模式-責任模式

設計模式 Android Java 今天來說說程序員小猿和產品就關於需求發生的故事。前不久,小猿收到了產品的需求。產品經理:小猿,為了迎合大眾屌絲用戶的口味,我們要放一張圖,要露點的。小猿:......露點?你大爺的,讓身為正義與純潔化身的我做這種需求,還露點。產品經理:誤會誤會,是放一張暴露一點

Java設計模式-責任模式

對象行為型模式 結束 PE 缺點 滿足 repl top 調用 規則 責任鏈模式又稱為職責鏈模式,在23種設計模式中歸類為行為型模式。行為型模式可以分為類行為型模式和對象行為型模式。 類行為型模式使用繼承關系在幾個類之間分配行為,類行為型模式主要通過多態等方式來分配父類與子

重走Java設計模式——責任模式(Chain of Responsibility Pattern)

責任鏈模式 定義 使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合關係,將這些物件連結成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。 程式碼示例 我們建立抽象類AbstractLogger,帶有詳細的日誌記錄級別。然後我們建立三

從原始碼角度理解Java設計模式--責任模式

本文內容思維導圖如下:                                        

Java設計模式責任模式

責任鏈模式的定義:         使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。 責任鏈模式的重點是在“鏈”上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,並返回相

java設計模式:責任模式

責任鏈模式 將接收者物件連成一條鏈,並在該鏈上傳遞請求,直到有一個接收者物件處理他,通過讓更多物件有機會處理請求,避免了請求傳送者和接收者之間的耦合。 下面通過一個生活中的事例比如“申請折扣”來說明責任鏈模式。 你去買房子或買車,全款買的,所以想申請一個折扣,如果只是5

Java設計模式——責任模式(Chain of Responsibility)

責任鏈 責任鏈模式通俗來說就是關聯一串能夠處理事務的物件,使多個物件都有機會處理請求,從而避免了請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。【view事件處理】【okhttp interceptors

Java設計模式----責任模式

簡述:     前端時間再看一些類庫的原始碼,發現責任鏈模式的強大之處,尤其是和建造者模式的結合後強大的動態可擴充套件性更是牛逼的一塌糊塗。接下來趕緊了解一下吧!     我們先來了解一下什麼是責任鏈模式:     職責鏈模式(Chain of Responsibil

設計模式責任模式

[] .com repl ring replace servlet 就業 返回 array 責任鏈將處理請求在鏈條的節點上傳遞,每到一個節點可被處理或者也可不被處理。 典型的是在servlet中過濾器filter的的處理方式。當request請求或者response請求時,

設計模式——責任模式

IT ger bst student AR down OS 分享圖片 我們 背景: 想必獎學金大家都不陌生,在學校裏獎學金往往分為三種班獎學金、院級獎學金以及校級獎學金,但是我們往往苦於政策修改,不知道自己的獎學金該找誰領,於是乎就詢問順序就是:班級輔導員->學院老師

Groovy 設計模式 -- 責任模式

IT class att lin Language cti efault make each Chain of Responsibility Pattern http://groovy-lang.org/design-patterns.html#_chain_of_res

設計模式-責任模式在實際項目中的使用

模式 getc erro build strac orm collected pack server   最近一次叠代,參與了公司數據應用平臺的開發,其中負責的一塊功能早早的就完成了代碼的編寫工作,即將進入測試階段,因為有時間思考和總結代碼編寫中遇到的難題,便想著將代碼做一

設計模式 | 責任模式及典型應用

本文的主要內容: 介紹責任鏈模式 請假流程示例 責任鏈模式總結 原始碼分析Tomcat Filter中的責任鏈模式 更多內容可訪問我的個人部落格:laijianfeng.org 關注【小旋鋒】微信公眾號,及時接收博文推送 **** 責任鏈模式 一個事

設計模式 --- 責任模式

1.定義 使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,只到有物件處理它為止。   2.使用場景 多個物件可以處理同一請求,但具體由哪個物件處理則在執行時動態決定。 在請求處理者不明確的情況下向多

unity設計模式-----責任模式

責任鏈模式的定義:責任鏈模式指的是--某個請求需要多個物件進行處理,從而避免請求的傳送者和接收之間的耦合關係,將這些物件連成一條鏈子,並沿著這條鏈子傳遞請求,直到有物件處理它為止 例如: 從生活中的例子可以發現,某個請求可能需要幾個人的審批,即使技術經理審批完了,還需要上一級的審批.   &

設計模式-行為型模式-責任模式

設計模式-行為型模式-責任鏈模式 定義 將請求沿著鏈傳遞,然後直到物件處理即可。 UML圖 程式碼 基本的責任鏈 public class Test{ public void test(int i, Request request){ if(i == 1){

設計模式-責任模式(responsibility)

責任鏈模式是行為模式的一種,該模式構造一系列的分別擔當不同職責的類的物件(HeaderCar、BodyCar、FooterCar)來共同完成一個任務,這些類的物件之間像鏈條一樣緊密相連。 角色和職責: 1.抽象處理者(Handler)-CarHandler:   2.具體處理者(Concr

移動開發之設計模式- 責任模式(IOS&Android)

資源 完全參照 責任鏈模式|菜鳥教程但不包括IOS程式碼 責任鏈模式 顧名思義,責任鏈模式(Chain of Responsibility Pattern)為請求建立了一個接收者物件的鏈。這種模式給予請求的型別,對請求的傳送者和接收者進行解耦。這種型別的設計模式屬於行為型模式。

“戲”說設計模式——責任模式

首先請出今天的主人公——“齊天大聖”孫悟空 原創文章,禁止轉載https://blog.csdn.net/wfy2695766757   小時候每到假期,電視上就會播出大家耳熟能詳的“西遊記” 。 那麼今天我們就通過“齊天大聖”孫悟空大鬧天宮來描述23種設計模式中之一的