欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文搞懂Java設(shè)計模式之責(zé)任鏈模式

 更新時間:2020年12月20日 08:38:45   作者:lzy_tinyjoy  
這篇文章主要給大家介紹了關(guān)于Java設(shè)計模式之責(zé)任鏈模式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

簡述:

    前端時間再看一些類庫的源碼,發(fā)現(xiàn)責(zé)任鏈模式的強(qiáng)大之處,尤其是和建造者模式的結(jié)合后強(qiáng)大的動態(tài)可擴(kuò)展性更是牛逼的一塌糊涂。接下來趕緊了解一下吧!

    我們先來了解一下什么是責(zé)任鏈模式:

    職責(zé)鏈模式(Chain of Responsibility):使多個對象都有機(jī)會處理同一個請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。

應(yīng)用場景:

     為完成同一個請求,如果存在多個請求處理器以及未知請求處理器個數(shù)或者請求處理器可動態(tài)配置的情況下,可以考慮使用責(zé)任鏈模式。如OKHttp的攔截器就是使用的責(zé)任鏈模式。

實例UML圖:

實例執(zhí)行流程圖:

實例:

    1、實例場景

    在公司內(nèi)部員工請假一般情況是這樣的:員工在OA系統(tǒng)中提交一封請假郵件,該郵件會自動轉(zhuǎn)發(fā)到你的直接上級領(lǐng)導(dǎo)郵箱里,如果你的請假的情況特殊的話,該郵件也會轉(zhuǎn)發(fā)到你上級的上級的郵箱,根據(jù)請假的情況天數(shù)多少,系統(tǒng)會自動轉(zhuǎn)發(fā)相應(yīng)的責(zé)任人的郵箱。我們就以這樣一種場景為例完成一個責(zé)任鏈模式的代碼。為了更清晰的描述這種場景我們規(guī)定如下:

    ① GroupLeader(組長 ):他能批準(zhǔn)的假期為2天,如果請假天數(shù)超過2天就將請假郵件自動轉(zhuǎn)發(fā)到組長和經(jīng)理郵箱。

    ② Manager(經(jīng)理):他能批準(zhǔn)的假期為4天以內(nèi),如果請假天數(shù)大于4天將該郵件轉(zhuǎn)發(fā)到自動轉(zhuǎn)發(fā)到組長、經(jīng)理和部門領(lǐng)導(dǎo)的郵箱。

    ③ DepartmentHeader(部門領(lǐng)導(dǎo)):他能批準(zhǔn)的假期為7天以內(nèi),如果大于7天就只批準(zhǔn)7天。

    2、實例代碼

    我們清楚了上面的場景以后就開始定義模型:

        ①根據(jù)面向?qū)ο蟮乃枷胛覀兊枚x需要用到的對象。OK,為了更加清楚的說明“責(zé)任鏈模式的可擴(kuò)展性”問題我這里采用了建造者模式構(gòu)造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 + "]";
 }
 
}

        接下來再定義“批準(zhǔn)結(jié)果”對象Result:

/**
 * 類描述:結(jié)果對象
 *
 * @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和獲取請求結(jié)果Result。

/**
 * 接口描述:處理請求
 *
 * @author lzy
 *
 */
public interface Ratify {
 // 處理請求
 public Result deal(Chain chain);
 
 /**
 * 接口描述:對request和Result封裝,用來轉(zhuǎn)發(fā)
 */
 interface Chain {
 // 獲取當(dāng)前request
 Request request();
 
 // 轉(zhuǎn)發(fā)request
 Result proceed(Request request);
 }
}

   看到上面的接口,可能會有人迷惑:在接口Ratify中為什么又定義一個Chain接口呢?其實這個接口是單獨(dú)定義還是內(nèi)部接口沒有太大關(guān)系,但是考慮到Chain接口與Ratify接口的關(guān)系為提高內(nèi)聚性就定義為內(nèi)部接口了。定義Ratify接口是為了處理Request那為什么還要定義Chain接口呢?這正是責(zé)任鏈接口的精髓之處:轉(zhuǎn)發(fā)功能及可動態(tài)擴(kuò)展“責(zé)任人”,這個接口中定義了兩個方法一個是request()就是為了獲取request,如果當(dāng)前Ratify的實現(xiàn)類獲取到request之后發(fā)現(xiàn)自己不能處理或者說自己只能處理部分請求,那么他將自己的那部分能處理的就處理掉,然后重新構(gòu)建一個或者直接轉(zhuǎn)發(fā)Request給下一個責(zé)任人。可能這點(diǎn)說的不容易理解,我舉個例子,在Android與后臺交互中如果使用了Http協(xié)議,當(dāng)然我們可能使用各種Http框架如HttpClient、OKHttp等,我們只需要發(fā)送要請求的參數(shù)就直接等待結(jié)果了,這個過程中你可能并沒有構(gòu)建請求頭,那么框架幫你把這部分工作給做了,它做的工程中如果使用了責(zé)任鏈模式的話,它肯定會將Request進(jìn)行包裝(也就是添加請求頭)成新的Request,我們姑且加他為Request1,如果你又希望Http做本地緩存,那么Request1又會被轉(zhuǎn)發(fā)到并且重新進(jìn)一步包裝為Request2??傊瓹hain這個接口就是起到對Request進(jìn)行重新包裝的并將包裝后的Request進(jìn)行下一步轉(zhuǎn)發(fā)的作用。如果還不是很明白也沒關(guān)系,本實例會演示這一功能機(jī)制。

    ③上面說Chain是用來對Request重新包裝以及將包裝后的Request進(jìn)行下一步轉(zhuǎn)發(fā)用的,那我們就具體實現(xiàn)一下:

/**
 * 類描述:實現(xiàn)Chain的真正的包裝Request和轉(zhuǎn)發(fā)功能
 *
 * @author lzy
 *
 */
public class RealChain implements Chain {
 public Request request;
 public List<Ratify> ratifyList;
 public int index;
 
 /**
 * 構(gòu)造方法
 *
 * @param ratifyList
 * Ratify接口的實現(xiàn)類集合
 * @param request
 * 具體的請求Request實例
 * @param index
 * 已經(jīng)處理過該request的責(zé)任人數(shù)量
 */
 public RealChain(List<Ratify> ratifyList, Request request, int index) {
 this.ratifyList = ratifyList;
 this.request = request;
 this.index = index;
 }
 
 /**
 * 方法描述:具體轉(zhuǎn)發(fā)功能
 */
 @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;
 }
 
 /**
 * 方法描述:返回當(dāng)前Request對象或者返回當(dāng)前進(jìn)行包裝后的Request對象
 */
 @Override
 public Request request() {
 return request;
 }
 
}

    ④ 經(jīng)過上面幾步我們已經(jīng)完成了責(zé)任鏈模式的核心功能,接下來我們定義幾個相關(guān)責(zé)任對象:GroupLeader、Manager和DepartmentHeader,并讓他們實現(xiàn)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() + "平時表現(xiàn)不錯,而且現(xiàn)在項目也不忙")
  .build();
 return chain.proceed(newRequest);
 }
 
 return new Result(true, "GroupLeader:早去早回");
 }
}
 
 
/**
 * 經(jīng)理
 *
 * @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) {
 // 構(gòu)建新的Request
 Request newRequest = new Request.Builder().newRequest(request)
  .setManagerInfo(request.name() + "每月的KPI考核還不錯,可以批準(zhǔn)")
  .build();
 return chain.proceed(newRequest);
 
 }
 return new Result(true, "Manager:早點(diǎn)把事情辦完,項目離不開你");
 }
 
}
 
/**
 * 部門領(lǐng)導(dǎo)
 *
 * @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:不要著急,把事情處理完再回來!");
 }
 
}

    到此,責(zé)任鏈模式的一個Demo就算是完成了,但為了方便調(diào)用,我們在寫一個該責(zé)任鏈模式的客戶端工具類ChainOfResponsibilityClient 如下:

/**
 * 類描述:責(zé)任鏈模模式工具類
 *
 * @author lzy
 *
 */
public class ChainOfResponsibilityClient {
private ArrayList<Ratify> ratifies;
 
 public ChainOfResponsibilityClient() {
  ratifies = new ArrayList<Ratify>();
 }
 
 /**
 * 方法描述:為了展示“責(zé)任鏈模式”的真正的迷人之處(可擴(kuò)展性),在這里構(gòu)造該方法以便添加自定義的“責(zé)任人”
 *
 * @param ratify
 */
 public void addRatifys(Ratify ratify) {
  ratifies.add(ratify);
 }
 
 /**
 * 方法描述:執(zhí)行請求
 *
 * @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,我們測試一下見證奇跡吧:

/**
 * 類描述:責(zé)任鏈模式測試類
 *
 * @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("結(jié)果:" + result.toString());
 } 
}

    這個請求是張三請事假5天,按照我們的約定應(yīng)該請求會到達(dá)部門領(lǐng)導(dǎo)手里,且他看到請求的樣式為:“ [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=張三平時表現(xiàn)不錯,而且現(xiàn)在項目也不忙, managerInfo=張三每月的KPI考核還不錯,可以批準(zhǔn), 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=張三平時表現(xiàn)不錯,而且現(xiàn)在項目也不忙, managerInfo=null, departmentHeaderInfo=null]
DepartmentHeader=====>request:Request [name=張三, reason=事假, days=5customInfo=null, groupLeaderInfo=張三平時表現(xiàn)不錯,而且現(xiàn)在項目也不忙, managerInfo=張三每月的KPI考核還不錯,可以批準(zhǔn), departmentHeaderInfo=null]
結(jié)果:Result [isRatify=true, info=DepartmentHeader:不要著急,把事情處理完再回來!]

    OK,和預(yù)期一樣完美。剛開始就提到這個責(zé)任鏈模式是可以“動態(tài)擴(kuò)展的”,我們驗證一下,首先自定義一個“責(zé)任人”(其實也可以叫攔截器):

/**
 * 類描述:自定義“責(zé)任人”
 *
 * @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() + "請的是事假,而且很著急,請領(lǐng)導(dǎo)重視一下")
   .build();
  System.out.println("CustomInterceptor=>轉(zhuǎn)發(fā)請求");
  return chain.proceed(newRequest);
  }
  return new Result(true, "同意請假");
 }
 
}

    然后在測試類Main.java中調(diào)用如下:

/**
 * 類描述:責(zé)任鏈模式測試類
 *
 * @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("結(jié)果:" + result.toString());
 }
 
}

    OK,看一下日志:

 

      哈哈,責(zé)任鏈模式功能之強(qiáng)大還要多用多體會呀!

到此這篇關(guān)于Java設(shè)計模式之責(zé)任鏈模式的文章就介紹到這了,更多相關(guān)Java設(shè)計模式之責(zé)任鏈模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java list 比較詳解及實例

    java list 比較詳解及實例

    這篇文章主要介紹了java list 比較詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • spring boot springMVC擴(kuò)展配置實現(xiàn)解析

    spring boot springMVC擴(kuò)展配置實現(xiàn)解析

    這篇文章主要介紹了spring boot springMVC擴(kuò)展配置實現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • springboot連接多個數(shù)據(jù)庫的實現(xiàn)方法

    springboot連接多個數(shù)據(jù)庫的實現(xiàn)方法

    有時候一個SpringBoot項目需要同時連接兩個數(shù)據(jù)庫,本文就來介紹一下springboot連接多個數(shù)據(jù)庫的實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • Java創(chuàng)建student類詳細(xì)代碼例子

    Java創(chuàng)建student類詳細(xì)代碼例子

    這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建student類的相關(guān)資料,學(xué)生類(Student)是一種面向?qū)ο蟮木幊谈拍?其主要用于描述學(xué)生的屬性和行為,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • BaseDao封裝增刪改查的代碼詳解

    BaseDao封裝增刪改查的代碼詳解

    本篇文章主要介紹對數(shù)據(jù)庫中表中的數(shù)據(jù)進(jìn)行增改刪查詢,封裝一個工具類(BaseDao)的詳細(xì)使用以及部分理論知識,并通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Java實現(xiàn)大文件的切割與合并操作示例

    Java實現(xiàn)大文件的切割與合并操作示例

    這篇文章主要介紹了Java實現(xiàn)大文件的切割與合并操作,結(jié)合實例形式分析了java基于io及util操作大文件按指定個數(shù)分割與合并相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • Java事務(wù)管理學(xué)習(xí)之JDBC詳解

    Java事務(wù)管理學(xué)習(xí)之JDBC詳解

    這篇文章主要介紹了Java事務(wù)管理學(xué)習(xí)之JDBC的相關(guān)資料,文中介紹的非常詳細(xì),相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • 關(guān)于JDK源碼中的@author unascribed注釋閑談

    關(guān)于JDK源碼中的@author unascribed注釋閑談

    這篇文章主要介紹了關(guān)于JDK源碼中的@author unascribed注釋閑談,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 深入淺析Spring-boot-starter常用依賴模塊

    深入淺析Spring-boot-starter常用依賴模塊

    這篇文章主要介紹了Spring-boot-starter常用依賴模塊及spring boot的兩大優(yōu)點(diǎn),需要的朋友可以參考下
    2018-01-01
  • java解析dbf之通過javadbf包生成和讀取dbf文件

    java解析dbf之通過javadbf包生成和讀取dbf文件

    這篇文章主要介紹了java通過javadbf讀取和生成DBF文件的方法,大家參考使用吧
    2014-01-01

最新評論