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