您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Java中責任鏈模式的作用有哪些,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
為完成同一個請求,如果存在多個請求處理器以及未知請求處理器個數或者請求處理器可動態配置的情況下,可以考慮使用責任鏈模式。如OKHttp的攔截器就是使用的責任鏈模式。
實例執行流程圖:
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中責任鏈模式的作用有哪些,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。