責任鏈模式(Chain of Responsibility Pattern)是一種行為型設計模式,它允許多個對象按照順序處理請求,并且每個對象可以選擇自己是否處理該請求或將其傳遞給下一個對象。這種模式將請求的發送者和接收者解耦,同時提供了更大的靈活性和可擴展性。
責任鏈模式通過將多個處理請求的對象組成一條鏈,使請求在鏈上傳遞,直到有一個對象處理它為止。每個處理對象都負責判斷自己能否處理該請求,如果可以則進行處理,否則將請求傳遞給下一個處理對象。這樣,請求發送者無需知道具體的處理對象,只需將請求發送到責任鏈上即可。
責任鏈模式包含以下角色:
通過責任鏈模式,我們可以動態地組合處理對象,靈活地配置處理流程,這種解耦使得系統更加靈活和可擴展。
責任鏈模式常用于以下場景:
常見的實際應用場景包括:
責任鏈模式在這些場景中可以減少代碼的耦合性,提高代碼的可維護性和可擴展性。
優點:
缺點:
在實際應用中,我們需要根據具體情況評估責任鏈模式的優缺點,并合理地選擇使用或者改進這個模式。
要實現責任鏈模式,我們按照以下步驟進行:
以下是一個簡單的示例,演示如何使用責任鏈模式處理請假申請:
步驟一:定義處理者接口(Handler)
/** * <p> * 責任鏈模式——抽象類處理器 * </p> */public abstract class AbstractHandler { /** * 責任鏈中的下一個元素 */ protected AbstractHandler nextHandler; public AbstractHandler setNextChain(AbstractHandler nextHandler) { this.nextHandler = nextHandler; return nextHandler; } /** * 責任鏈處理邏輯 */ public void linkChain(LeaveRequest request) { handler(request); //這里還可以加入其他方法 if (Objects.nonNull(nextHandler)) { nextHandler.linkChain(request); } } /** * 抽象方法 */ protected abstract void handler(LeaveRequest request);}
請求對象為:
@Getterpublic class LeaveRequest { private final String employee; private final int days; public LeaveRequest(String employee, int days) { this.employee = employee; this.days = days; }}
步驟二:實現具體處理者類(ConcreteHandler)
@Slf4jpublic class Handler1 extends AbstractHandler { @Override public void handler(LeaveRequest request) { if (request.getDays() <= 3) { log.info("ConcreteHandlerA 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}@Slf4jpublic class Handler2 extends AbstractHandler { @Override public void handler(LeaveRequest request) { if (request.getDays() > 3 && request.getDays() <= 7) { log.info("ConcreteHandlerB 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}@Slf4jpublic class Handler3 extends AbstractHandler { @Override protected void handler(LeaveRequest request) { if (request.getDays() > 7) { log.info("ConcreteHandlerC 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}
步驟三:在客戶端代碼中創建責任鏈,并將請求發送到責任鏈上的第一個處理者
public class ChainPatternDemo { private static AbstractHandler getChainOfHandler() { AbstractHandler handler1 = new Handler1(); AbstractHandler handler2 = new Handler2(); AbstractHandler handler3 = new Handler3(); //可以自定義鏈路順序 handler1.setNextChain(handler2).setNextChain(handler3); return handler1; } public static void main(String[] args) { AbstractHandler chain = getChainOfHandler(); LeaveRequest request1 = new LeaveRequest("張三", 2); chain.linkChain(request1); LeaveRequest request2 = new LeaveRequest("李四", 5); chain.linkChain(request2); LeaveRequest request3 = new LeaveRequest("王五", 10); chain.linkChain(request3); }}
在上述示例中,我們定義了三個具體處理者類:Handler1、Handler2和Handler3,它們分別處理請假申請。客戶端代碼創建了責任鏈,并將請求發送給第一個處理者Handler1。每個具體處理者判斷自己是否能夠處理該請求,如果可以則進行處理,否則傳遞給下一個處理者。
運行以上代碼,輸出結果為:
ConcreteHandlerA 處理了 張三 的請假申請,天數為:2ConcreteHandlerB 處理了 李四 的請假申請,天數為:5ConcreteHandlerC 處理了 王五 的請假申請,天數為:10
這只是一個簡單示例,實際使用時可以根據業務需求進行適當的擴展和修改。
在使用責任鏈模式時,需要注意以下幾點:
我們可以通過建造者模式來創建責任鏈中的處理者對象。這種優化可以使責任鏈的創建和配置更加靈活和可拓展,符合開閉原則。
優化后的示例代碼:
/** * <p> * 責任鏈模式——抽象類處理器 * </p> */public abstract class AbstractHandler { /** * 責任鏈中的下一個元素 */ protected AbstractHandler nextHandler; private void setNextChain(AbstractHandler nextHandler) { this.nextHandler = nextHandler; } /** * 責任鏈處理邏輯 */ public void linkChain(LeaveRequest request) { handler(request); //這里還可以加入其他方法 if (Objects.nonNull(nextHandler)) { nextHandler.linkChain(request); } } /** * 抽象方法 */ protected abstract void handler(LeaveRequest request); public static class Builder { private AbstractHandler head; private AbstractHandler tail; public Builder addHandler(AbstractHandler handler) { if (this.head == null) { this.head = this.tail = handler; return this; } this.tail.setNextChain(handler); this.tail = handler; return this; } public AbstractHandler build() { return this.head; } }}
public class ChainPatternDemo { private static AbstractHandler getChainOfHandler() { return new AbstractHandler.Builder() .addHandler(new Handler1()) .addHandler(new Handler2()) .addHandler(new Handler3()) .build(); } public static void main(String[] args) { AbstractHandler chain = getChainOfHandler(); LeaveRequest request1 = new LeaveRequest("張三", 2); chain.linkChain(request1); LeaveRequest request2 = new LeaveRequest("李四", 5); chain.linkChain(request2); LeaveRequest request3 = new LeaveRequest("王五", 10); chain.linkChain(request3); }}
在客戶端代碼中,我們使用建造者模式創建了一個包含多個處理者的責任鏈,并發送了一個請假申請。責任鏈會按照添加處理者的順序依次處理請假申請,直到找到能夠處理該請求的處理者為止。
通過調用 addHandler 方法,我們可以逐步構建責任鏈,將處理者添加到責任鏈的末尾,由于 setNextChain() 不對外調用,作用域可以更改為 private,最后,通過調用 build 方法,我們可以獲取責任鏈的起始處理者。
Spring中我們可以使用 @Component,@Order 注解,來讓容器幫我們自動構建責任鏈,從而簡化代碼。
public abstract class Handler { abstract void handler(LeaveRequest request);}
@Order(value = 1)@Component@Slf4jpublic class HandlerA extends Handler{ @Override public void handler(LeaveRequest request) { if (request.getDays() <= 3) { log.info("ConcreteHandlerA 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}@Order(value = 2)@Component@Slf4jpublic class HandlerB extends Handler { @Override public void handler(LeaveRequest request) { if (request.getDays() > 3 && request.getDays() <= 7) { log.info("ConcreteHandlerB 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}@Order(value = 3)@Component@Slf4jpublic class HandlerC extends Handler{ @Override public void handler(LeaveRequest request) { if (request.getDays() > 7) { log.info("ConcreteHandlerC 處理了 " + request.getEmployee() + " 的請假申請,天數為:" + request.getDays()); } }}
測試:
@Testpublic void test() { for (Handler handler : handlerChain) { LeaveRequest request = new LeaveRequest("王五", 10); handler.handler(request); } }
輸出:
ConcreteHandlerC 處理了 王五 的請假申請,天數為:10
這種寫法有其利弊,優點是可以避免繁瑣的責任鏈構建過程,簡化了代碼結構;缺點是具體處理者類之間的執行順序不夠直觀,具體使用時需要權衡考慮。
責任鏈模式的優點在于其低耦合性、靈活性和可擴展性,使得我們能夠更加輕松地管理和組織復雜的處理流程。然而,也要注意其缺點,即請求未必被處理和對處理順序敏感的特點。
最重要的是,在實際應用中根據具體需求合理運用責任鏈模式,結合其他設計模式,以便在代碼結構和可維護性上取得更好的效果。
本文鏈接:http://www.www897cc.com/showinfo-26-70450-0.html一文搞懂設計模式—責任鏈模式
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com