Java設(shè)計(jì)模式之責(zé)任鏈模式
設(shè)計(jì)者往往會(huì)用攔截器去代替動(dòng)態(tài)代理,然后將攔截器的接口提供給開(kāi)發(fā)者,從而簡(jiǎn)化開(kāi)發(fā)者的開(kāi)發(fā)難度,但是攔截器可能有多個(gè)。舉個(gè)例子,一個(gè)程序員需要請(qǐng)假一周,如果把請(qǐng)假申請(qǐng)單看成一個(gè)對(duì)象,那么它需要經(jīng)過(guò)項(xiàng)目經(jīng)理、部門(mén)經(jīng)理、人事等多個(gè)角色的審批,每個(gè)角色都有機(jī)會(huì)通過(guò)攔截這個(gè)申請(qǐng)單進(jìn)行審批或者修改。這事就要考慮提供項(xiàng)目經(jīng)理、部門(mén)經(jīng)理和人事的處理邏輯,所以需要提供3個(gè)攔截器,二傳遞的則是請(qǐng)假申請(qǐng)單。
當(dāng)一個(gè)對(duì)象在一條鏈上被多個(gè)攔截器處理(攔截器也可以選擇不攔截處理它)時(shí),我們把這樣的設(shè)計(jì)模式成為責(zé)任鏈模式,它用于一個(gè)對(duì)象在多個(gè)角色中傳遞的場(chǎng)景。還是剛才的例子,申請(qǐng)單走到項(xiàng)目經(jīng)理,經(jīng)理可能把申請(qǐng)時(shí)間“一周”改為“5天”,從而影響了后面的審批,后面的審批都要根據(jù)前面的結(jié)果進(jìn)行。這個(gè)時(shí)候可以考慮用層層代理來(lái)實(shí)現(xiàn),就是當(dāng)申請(qǐng)單(target)走到項(xiàng)目經(jīng)理處,使用第一個(gè)動(dòng)態(tài)代理proxy1,。當(dāng)它走到部門(mén)經(jīng)理處,部門(mén)經(jīng)理會(huì)得到一個(gè)在項(xiàng)目經(jīng)理的代理proxy1基礎(chǔ)上生成的proxy2來(lái)處理部門(mén)經(jīng)理的邏輯。當(dāng)它走到人事處,會(huì)在proxy2的基礎(chǔ)上生成proxy3.如果還有其他角色,依次類(lèi)推即可,可用下圖來(lái)描述攔截邏輯:

我們定義下面的攔截器接口:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:15
* @Description:攔截器接口
**/
public interface Interceptor {
boolean before(Object proxy, Object target, Method method,Object[] args);
void around(Object proxy,Object target,Method method,Object[] args);
void after(Object proxy,Object target,Method method,Object[] args);
}
再定義3個(gè)攔截器:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:19
* @Description:攔截器1
**/
public class Interceptor1 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器1]的before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器1]的after方法");
}
}
/**
* @Auther: haozz
* @Date: 2018/5/27 22:19
* @Description:攔截器2
**/
public class Interceptor2 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器2]的before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器2]的after方法");
}
}
/**
* @Auther: haozz
* @Date: 2018/5/27 22:19
* @Description:攔截器3
**/
public class Interceptor3 implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器3]的before方法");
return true;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("[攔截器3]的after方法");
}
}
我們使用上一篇(Java動(dòng)態(tài)代理之?dāng)r截器的應(yīng)用)中用到的InterceptorJdkProxy類(lèi),測(cè)試一下這段代碼。如下:
@Test
public void MyTest(){
HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.csdn.blog.impl.Interceptor1");
HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(proxy1,"com.csdn.blog.impl.Interceptor2");
HelloWorld proxy3 = (HelloWorld) InterceptorJdkProxy.bind(proxy2,"com.csdn.blog.impl.Interceptor3");
proxy3.sayHelloWorld();
}
運(yùn)行這段diamante后得到這樣的結(jié)果,請(qǐng)注意觀察其方法的執(zhí)行順序:
[攔截器3]的before方法
[攔截器2]的before方法
[攔截器1]的before方法
Hello World
[攔截器1]的after方法
[攔截器2]的after方法
[攔截器3]的after方法
before方法按照最后一個(gè)攔截器到第一個(gè)攔截器的加載順序運(yùn)行,而after方法則按照從第一個(gè)攔截器到最后一個(gè)攔截器的加載順序運(yùn)行。
從代碼中可見(jiàn),責(zé)任鏈模式的優(yōu)點(diǎn)在于我們可以在傳遞鏈上加入新的攔截器,增加攔截邏輯,其缺點(diǎn)是會(huì)增加代理和反射,而代理和反射的性能不高。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
SpringBoot如何進(jìn)行參數(shù)校驗(yàn)實(shí)例詳解
開(kāi)發(fā)過(guò)程中,后臺(tái)的參數(shù)校驗(yàn)是必不可少的,下面這篇文章主要給大家介紹了關(guān)于SpringBoot如何進(jìn)行參數(shù)校驗(yàn)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-01-01
一個(gè)Java中BigDecimal的問(wèn)題記錄
這篇文章主要給大家介紹了關(guān)于Java中一個(gè)BigDecimal問(wèn)題的相關(guān)資料,通過(guò)文中介紹的方法可以很方便的解決BigDecimal進(jìn)行計(jì)算的時(shí)候不管怎么計(jì)算,最后得到的值都沒(méi)有變化的問(wèn)題,需要的朋友可以參考下2021-11-11
基于Java語(yǔ)言MD5加密Base64轉(zhuǎn)換方法
這篇文章主要為大家詳細(xì)介紹了基于Java語(yǔ)言的MD5加密Base64轉(zhuǎn)換方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
java基于C/S模式實(shí)現(xiàn)聊天程序(服務(wù)器)
這篇文章主要為大家詳細(xì)介紹了java基于C/S模式實(shí)現(xiàn)聊天程序的服務(wù)器篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Java元素排序Comparable與Comparator的區(qū)別
這篇文章主要介紹了Java元素排序Comparable與Comparator的區(qū)別,二者都是頂級(jí)的接口,但擁有的方法和用法是不同的,下面我們分別來(lái)看看具體是怎樣的區(qū)別吧2022-05-05
SpringBoot+mybatis+Vue實(shí)現(xiàn)前后端分離項(xiàng)目的示例
本文主要介紹了SpringBoot+mybatis+Vue實(shí)現(xiàn)前后端分離項(xiàng)目的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
Apache Commons Math3探索之多項(xiàng)式曲線擬合實(shí)現(xiàn)代碼
這篇文章主要介紹了Apache Commons Math3探索之多項(xiàng)式曲線擬合實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-10-10

