責(zé)任鏈模式

責(zé)任鏈模式

責(zé)任鏈模式的優(yōu)缺點(diǎn)

責(zé)任鏈模式與if…else…相比,他的耦合性要低一些,因?yàn)樗褩l件判定都分散到了各個(gè)處理類中,并且這些處理類的優(yōu)先處理順序可以隨意設(shè)定。責(zé)任鏈模式也有缺點(diǎn),這與if…else…語句的缺點(diǎn)是一樣的,那就是在找到正確的處理類之前,所有的判定條件都要被執(zhí)行一遍,當(dāng)責(zé)任鏈比較長時(shí),性能問題比較嚴(yán)重。

責(zé)任鏈模式的適用場(chǎng)景

假如使用if…else…語句來組織一個(gè)責(zé)任鏈時(shí)感到力不從心,代碼看上去很糟糕時(shí),就可以使用責(zé)任鏈模式來進(jìn)行重構(gòu)。

示例

定義一個(gè)處理優(yōu)先級(jí)類Level

public class Level {
    private int level = 0;

    public Level(int level) {
        this.level = level;
    }

    public boolean above(Level level) {
        if (this.level >= level.level) {
            return true;
        }
        return false;
    }
}

模擬一個(gè)處理請(qǐng)求Request類,該類會(huì)包含有處理優(yōu)先級(jí)類,以提示后面的處理器

public class Request {
    Level level;

    public Request(Level level) {
        this.level = level;
    }

    public Level getLevel() {
        return level;
    }
}

模擬響應(yīng)類Response


public class Response {
}

定義一個(gè)抽象的處理抽象類Handler,之所有使用抽象類而不是純接口在于抽象類可以包含一些默認(rèn)的實(shí)現(xiàn)方法,對(duì)于確定的處理過程我們可以將其寫到抽象類的具體實(shí)現(xiàn)中,而對(duì)于每個(gè)處理器都不一樣的,這里我們只定義一個(gè)抽象方法,由具體的實(shí)現(xiàn)類去做具體的特定實(shí)現(xiàn):

public abstract class Handler {

    public final Response handleRequest(Request request, FilterChain chain) {
        Response response = null;
        if (this.getHandlerLevel().above(request.getLevel())) {
            response = this.response(request);
        } else {
            chain.doFilter(request);
        }
        return response;
    }

    protected abstract Level getHandlerLevel();

    public abstract Response response(Request request);
}

處理器1 ConcreteHandler1:

public class ConcreteHandler1 extends Handler{
    @Override
    protected Level getHandlerLevel() {
        return new Level(1);
    }

    @Override
    public Response response(Request request) {
        System.out.println("-----請(qǐng)求由處理器1進(jìn)行處理-----");
        return null;
    }
}

處理器2 ConcreteHandler2:

public class ConcreteHandler2 extends Handler {
    @Override
    protected Level getHandlerLevel() {
        return new Level(3);
    }
    @Override
    public Response response(Request request) {
        System.out.println("-----請(qǐng)求由處理器2進(jìn)行處理-----");
        return null;
    }
}

處理器3 ConcreteHandler3:

public class ConcreteHandler3 extends Handler{
    @Override
    protected Level getHandlerLevel() {
        return new Level(5);
    }
    @Override
    public Response response(Request request) {
        System.out.println("-----請(qǐng)求由處理器3進(jìn)行處理-----");
        return null;
    }
}

接下來出場(chǎng)是最關(guān)鍵的串聯(lián)類FilterChain,通過它我們來串聯(lián)上面提到的各個(gè)Handler:

import org.springframework.util.CollectionUtils;

import java.util.List;

public class FilterChain {

    private int pos = 0;

    private List<Handler> handlerList;

    public FilterChain(List<Handler> handlerList) {
        this.handlerList = handlerList;
    }

    /**
     * 洋蔥模型,處理后能夠返回
     *
     * @param request
     * @return
     */
    public Response doFilter(Request request) {
        if (!CollectionUtils.isEmpty(handlerList) && pos < handlerList.size()) {
            System.out.println(String.format("the %d time for processing", pos + 1));
            return handlerList.get(pos++).handleRequest(request, this);
        }
        return null;
    }
}

OK,接下來寫個(gè)單測(cè)試一下:

import com.netease.learn.designPattern.fliterChain.*;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

/**
 * 責(zé)任鏈模式測(cè)試類
 */
public class FliterChainTest {

    @Test
    public void test() {
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        Handler handler3 = new ConcreteHandler3();
        List<Handler> handlerList = Arrays.asList(handler1, handler2, handler3);
        FilterChain filterChain = new FilterChain(handlerList);
        filterChain.doFilter(new Request(new Level(4)));

    }
}

備注:

  1. 在實(shí)際的工程中,我們通常在Spring 的XML文件中去初始化各個(gè)chain,然后將他們的實(shí)例注入到FilterChain中。

輸出如下:

the 1 time for processing
the 2 time for processing
the 3 time for processing
-----請(qǐng)求由處理器3進(jìn)行處理-----

參考資料

  1. 代碼倉庫-責(zé)任鏈模式
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容