Java中常用的設(shè)計(jì)模式之責(zé)任鏈模式詳解
優(yōu)點(diǎn)
1.降低耦合度。它將請(qǐng)求的發(fā)送者和接收者解耦。
2.簡(jiǎn)化了對(duì)象。使得對(duì)象不需要知道鏈的結(jié)構(gòu)。
3.增強(qiáng)給對(duì)象指派職責(zé)的靈活性。通過(guò)改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序,允許動(dòng)態(tài)地新增或者刪除責(zé)任。
4、增加新的請(qǐng)求處理類很方便。
缺點(diǎn)
1.不能保證請(qǐng)求一定被接收。
2.系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時(shí)不太方便,可能會(huì)造成循環(huán)調(diào)用。
3.可能不容易觀察運(yùn)行時(shí)的特征,有礙于除錯(cuò)。
使用場(chǎng)景
1.有多個(gè)對(duì)象可以處理同一個(gè)請(qǐng)求,具體哪個(gè)對(duì)象處理該請(qǐng)求由運(yùn)行時(shí)刻自動(dòng)確定。
2.在不明確指定接收者的情況下,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求。
3.可動(dòng)態(tài)指定一組對(duì)象處理請(qǐng)求。
一、實(shí)現(xiàn)方式
假設(shè)一個(gè)場(chǎng)景,學(xué)校里,校長(zhǎng)的職能大于老師,老師的職能大于學(xué)生,基于這樣的鏈路關(guān)系,學(xué)生處理不了的事情上報(bào)給老師,老師處理不了的事情上報(bào)給校長(zhǎng)。
1、處理抽象類
package com.asurplus.common.handle.style1; /** * 處理抽象類 */ public abstract class Handler { /** * 下一個(gè)處理類 */ protected Handler handler; public void setHandler(Handler handler) { this.handler = handler; } public Handler getHandler() { return handler; } /** * 處理事件 * * @param request */ public abstract void handlerRequest(String request); }
2、學(xué)生處理類
package com.asurplus.common.handle.style1; import lombok.extern.slf4j.Slf4j; /** * 學(xué)生處理類 */ @Slf4j public class StudentHandler extends Handler { @Override public void handlerRequest(String request) { if ("打掃衛(wèi)生".equals(request)) { log.info("學(xué)生處理中"); } else { this.handler.handlerRequest(request); } } }
學(xué)生能處理“打掃衛(wèi)生”這件事,如果是其他事件,交給他的下一個(gè)元素
3、老師處理類
package com.asurplus.common.handle.style1; import lombok.extern.slf4j.Slf4j; /** * 老師處理類 */ @Slf4j public class TeacherHandler extends Handler { @Override public void handlerRequest(String request) { if ("批改試卷".equals(request)) { log.info("老師處理中"); } else { this.handler.handlerRequest(request); } } }
老師能處理“批改試卷”這件事,如果是其他事件,交給他的下一個(gè)元素
4、校長(zhǎng)處理類
package com.asurplus.common.handle.style1; import lombok.extern.slf4j.Slf4j; /** * 校長(zhǎng)處理類 */ @Slf4j public class HeadHandler extends Handler { @Override public void handlerRequest(String request) { if ("學(xué)籍問(wèn)題".equals(request)) { log.info("校長(zhǎng)處理中"); } else { log.error("無(wú)法處理該事件"); } } }
校長(zhǎng)能處理“學(xué)籍問(wèn)題”這件事,如果是其他事件,由于我們的責(zé)任鏈只有三級(jí),都處理不了,只能打印日志了
5、測(cè)試
package com.asurplus.common.handle.style1; /** * 責(zé)任鏈模式 */ public class TestMain { public static void main(String[] args) { // 學(xué)生處理器 StudentHandler studentHandler = new StudentHandler(); // 老師處理器 TeacherHandler teacherHandler = new TeacherHandler(); // 校長(zhǎng)處理器 HeadHandler headHandler = new HeadHandler(); // 老師的上一級(jí)是校長(zhǎng) teacherHandler.setHandler(headHandler); // 學(xué)生的上一級(jí)是老師 studentHandler.setHandler(teacherHandler); // 處理 批改試卷 這件事 studentHandler.handlerRequest("批改試卷"); } }
輸出結(jié)果
可以看出,“批改試卷”這件事,被老師處理了。
二、實(shí)現(xiàn)方式
假設(shè)一個(gè)場(chǎng)景,在我們的電商系統(tǒng)中,當(dāng)創(chuàng)建一個(gè)訂單的時(shí)候,我們需要去校驗(yàn)很多的數(shù)據(jù),我們需要去判斷該商品存不存在,庫(kù)存還有沒(méi)有,價(jià)格對(duì)不對(duì),等等校驗(yàn)。
1、訂單信息類
package com.asurplus.common.handle.style2; import lombok.Builder; import lombok.Data; /** * 訂單信息 */ @Data @Builder public class Order { // 庫(kù)存 private int stock; // 單價(jià) private int price; }
2、訂單校驗(yàn)接口
package com.asurplus.common.handle.style2; /** * 校驗(yàn)器接口 * * @param <T> */ public interface OrderFilter<T> { /** * 業(yè)務(wù)邏輯 * * @param t * @return */ boolean execute(T t); }
3、庫(kù)存校驗(yàn)器
package com.asurplus.common.handle.style2; import lombok.extern.slf4j.Slf4j; /** * 庫(kù)存校驗(yàn)器 */ @Slf4j public class OrderStockFilter implements OrderFilter<Order> { @Override public boolean execute(Order order) { if (0 >= order.getStock()) { log.error("庫(kù)存不足"); return false; } return true; } }
4、價(jià)格校驗(yàn)器
package com.asurplus.common.handle.style2; import lombok.extern.slf4j.Slf4j; /** * 價(jià)格校驗(yàn)器 */ @Slf4j public class OrderPriceFilter implements OrderFilter<Order> { @Override public boolean execute(Order order) { if (0 > order.getPrice()) { log.error("價(jià)格錯(cuò)誤"); return false; } return true; } }
5、測(cè)試
package com.asurplus.common.handle.style2; import lombok.extern.slf4j.Slf4j; import java.util.Arrays; import java.util.List; /** * 責(zé)任鏈模式 */ @Slf4j public class TestMain { public static void main(String[] args) { // 建造者模式創(chuàng)建一個(gè)訂單 Order order = Order.builder().stock(0).price(0).build(); // 庫(kù)存校驗(yàn)器 OrderStockFilter orderQuantityFilter = new OrderStockFilter(); // 價(jià)格校驗(yàn)器 OrderPriceFilter orderPriceFilter = new OrderPriceFilter(); // 組裝成一個(gè)list List<OrderFilter<Order>> orderFilters = Arrays.asList(orderQuantityFilter, orderPriceFilter); boolean res = false; // 循環(huán)校驗(yàn) for (OrderFilter<Order> item : orderFilters) { res = item.execute(order); // 其中任何一項(xiàng)不通過(guò)就停止校驗(yàn) if (!res) { break; } } if (!res) { log.error("下單失敗"); } } }
被我們的“庫(kù)存校驗(yàn)器”校驗(yàn)不通過(guò),導(dǎo)致下單失敗。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring Security使用單點(diǎn)登錄的權(quán)限功能
本文主要介紹了Spring Security使用單點(diǎn)登錄的權(quán)限功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04java中的動(dòng)態(tài)代理與責(zé)任鏈模式詳解
這篇文章主要介紹了java中的動(dòng)態(tài)代理與責(zé)任鏈模式詳解,動(dòng)態(tài)代理提供了一種靈活且非侵入式的方式,可以對(duì)對(duì)象的行為進(jìn)行定制和擴(kuò)展,它在代碼重用、解耦和業(yè)務(wù)邏輯分離、性能優(yōu)化以及系統(tǒng)架構(gòu)中起到了重要的作用,需要的朋友可以參考下2023-08-08Spring Boot環(huán)境屬性占位符解析及類型轉(zhuǎn)換詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot環(huán)境屬性占位符解析及類型轉(zhuǎn)換的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作實(shí)例
這篇文章主要介紹了java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作,簡(jiǎn)單說(shuō)明了正則表達(dá)式常用元字符含義并結(jié)合實(shí)例形式分析了java基于正則表達(dá)式針對(duì)常用日期時(shí)間格式的判斷操作技巧,需要的朋友可以參考下2017-10-10改善Java代碼之慎用java動(dòng)態(tài)編譯
這篇文章主要介紹了改善Java代碼之慎用java動(dòng)態(tài)編譯,需要的朋友可以參考下2021-04-04Spring?容器初始化?register?與?refresh方法
這篇文章主要介紹了Spring?容器初始化?register?與?refresh方法,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07JAVA設(shè)計(jì)模式之訪問(wèn)者模式詳解
這篇文章主要介紹了JAVA設(shè)計(jì)模式之訪問(wèn)者模式詳解,訪問(wèn)者模式是對(duì)象的行為模式,訪問(wèn)者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作,需要的朋友可以參考下2015-04-04Spring Boot使用profile如何配置不同環(huán)境的配置文件
,springboot支持通過(guò)不同的profile來(lái)配置不同環(huán)境的配置,下面就大致介紹一下yml配置文件跟properties配置文件怎么使用profile配置不同環(huán)境的配置文件2018-01-01