国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一起學(xué)設(shè)計模式 - 責(zé)任鏈模式

SoapEye / 1796人閱讀

摘要:責(zé)任鏈模式屬于行為型模式的一種,將請求沿著一條鏈傳遞,直到該鏈上的某個對象處理它為止。責(zé)任鏈模式通過將請求和處理分離開來,以進(jìn)行解耦。源碼分析我們經(jīng)常使用的就使用到了責(zé)任鏈模式,創(chuàng)建一個除了要在應(yīng)用中做相應(yīng)配置外,還需要實(shí)現(xiàn)接口。

責(zé)任鏈模式(Chain Of Responsibility Pattern)屬于行為型模式的一種,將請求沿著一條傳遞,直到該上的某個對象處理它為止。

概述

定義如下:一個請求有多個對象來處理,這些對象形成一條鏈,根據(jù)條件確定具體由誰來處理,如果當(dāng)前對象不能處理則傳遞給該鏈中的下一個對象,直到有對象處理它為止。責(zé)任鏈模式通過將請求和處理分離開來,以進(jìn)行解耦。職責(zé)鏈模式結(jié)構(gòu)的核心在于引入了一個抽象處理者。

UML結(jié)構(gòu)圖

模式結(jié)構(gòu)

Handler(抽象處理者): 定義一個處理請求的接口,提供對后續(xù)處理者的引用

ConcreteHandler(具體處理者): 抽象處理者的子類,處理用戶請求,可選將請求處理掉還是傳給下家;在具體處理者中可以訪問鏈中下一個對象,以便請求的轉(zhuǎn)發(fā)。

案例

UML圖如下:

1.定義AbstractHandler(抽象處理者),使子類形成一條鏈

public abstract class AbstractHandler {

    private AbstractHandler handler;

    public abstract void handleRequest(String condition);

    public AbstractHandler getHandler() {
        return handler;
    }

    public void setHandler(AbstractHandler handler) {
        this.handler = handler;
    }
}

2.創(chuàng)建若干個ConcreteHandler(具體處理者)繼承AbstractHandler,在當(dāng)前處理者對象無法處理時,將執(zhí)行權(quán)傳給下一個處理者對象

public class ConcreteHandlerA extends AbstractHandler {

    @Override
    public void handleRequest(String condition) {
        if (condition.equals("A")) {
            System.out.println("ConcreteHandlerA處理");
        } else {
            System.out.println("ConcreteHandlerA不處理,由其他的Handler處理");
            super.getHandler().handleRequest(condition);
        }
    }
}

public class ConcreteHandlerB extends AbstractHandler {

    @Override
    public void handleRequest(String condition) {
        if (condition.equals("B")) {
            System.out.println("ConcreteHandlerB處理");
        } else {
            System.out.println("ConcreteHandlerB不處理,由其他的Handler處理");
            super.getHandler().handleRequest(condition);
        }
    }
}

public class ConcreteHandlerZ extends AbstractHandler {
    @Override
    public void handleRequest(String condition) {
        //一般是最后一個處理者
        System.out.println("ConcreteHandlerZ處理");
    }
}

3.創(chuàng)建ChainClient(測試類)

public class ChainClient {

    public static void main(String[] args) {
        AbstractHandler handlerA = new ConcreteHandlerA();
        AbstractHandler handlerB = new ConcreteHandlerB();
        AbstractHandler handlerZ = new ConcreteHandlerZ();
        // 如A處理不掉轉(zhuǎn)交給B
        handlerA.setHandler(handlerB);
        handlerB.setHandler(handlerZ);
        handlerA.handleRequest("Z");
    }

}

4.運(yùn)行效果

----------------------handleRequest("A")-------------------------
ConcreteHandlerA處理
----------------------handleRequest("B")-------------------------
ConcreteHandlerA不處理,由其他的Handler處理
ConcreteHandlerB處理
----------------------handleRequest("Z")-------------------------
ConcreteHandlerA不處理,由其他的Handler處理
ConcreteHandlerB不處理,由其他的Handler處理
ConcreteHandlerZ處理

可以看出,客戶端創(chuàng)建了三個處理者對象,并指定第一個處理者對象的下家是第二個處理者對象,第二個處理者對象的下家是第三個處理者對象。然后客戶端將請求傳遞給第一個處理者對象。

由于本示例的傳遞邏輯非常簡單:只要有下家,就傳給下家處理;如果沒有下家,就自行處理。因此,第一個處理者對象接到請求后,會將請求傳遞給第二個處理者對象。由于第二個處理者對象沒有下家,于是自行處理請求。活動時序圖如下所示。

純與不純

純:要么承擔(dān)全部責(zé)任,要么將責(zé)任推給下家,不允許出現(xiàn)某一個具體處理者對象在承擔(dān)了一部分或全部責(zé)任后又將責(zé)任向下傳遞的情況。

不純:允許某個請求被一個具體處理者部分處理后再向下傳遞,或者一個具體處理者處理完某請求后其后繼處理者可以繼續(xù)處理該請求,而且一個請求可以最終不被任何處理者對象所接收。

Filter源碼分析

我們經(jīng)常使用的Filter就使用到了責(zé)任鏈模式,創(chuàng)建一個Filter除了要在應(yīng)用中做相應(yīng)配置外,還需要實(shí)現(xiàn)javax.servlet.Filter接口。

@Configuration
public class MyFilter implements Filter {

    private final static Logger LOGGER = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LOGGER.info("init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        LOGGER.info("doFilter");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        LOGGER.info("destroy");
    }
}

使用DEBUG模式所看到的結(jié)果如下:

Filter

在源碼ApplicationFilterChain中,定義了一個ApplicationFilterConfig的數(shù)組來存放所有的Filter,使之形成鏈狀

public final class ApplicationFilterChain implements FilterChain {
    // 擴(kuò)容規(guī)則
    public static final int INCREMENT = 10;
    // Filter集,默認(rèn)大小為 0 個  
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
}

ApplicationFilterConfig 裝載規(guī)則

在應(yīng)用首次啟動時,會自動實(shí)例化對象,并從web應(yīng)用中讀取配置的Filter的信息,然后裝進(jìn)該容器。

public final class ApplicationFilterConfig implements FilterConfig, Serializable {
    // 省略代碼...
}

ApplicationFilterConfig 擴(kuò)容規(guī)則

//將過濾器添加到在此鏈條中執(zhí)行的過濾器集合中。
void addFilter(ApplicationFilterConfig filterConfig) {

    // 防止多次添加相同的過濾器
    for(ApplicationFilterConfig filter:filters)
        if(filter==filterConfig)
            return;

    if (n == filters.length) {
        // 定義一個在原基礎(chǔ)之上 +10 的新數(shù)組
        ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
        // 將源數(shù)組的元素拷貝到目標(biāo)數(shù)組中去
        System.arraycopy(filters, 0, newFilters, 0, n);
        // 重新賦值
        filters = newFilters;
    }
    //將變量filterConfig放入ApplicationFilterConfig數(shù)組中,并將當(dāng)前過濾器鏈里面擁有的過濾器數(shù)目+1
    filters[n++] = filterConfig;
}

addFilter 的使用

public static ApplicationFilterChain createFilterChain(ServletRequest request,Wrapper wrapper, Servlet servlet) {

        //如果沒有 servlet 要執(zhí)行,則返回null
        if (servlet == null)
            return null;

        // 創(chuàng)建和初始化過濾器鏈對象
        ApplicationFilterChain filterChain = null;
        if (request instanceof Request) {
            Request req = (Request) request;
            if (Globals.IS_SECURITY_ENABLED) {
                // 為了安全起見:不要回收
                filterChain = new ApplicationFilterChain();
            } else {
                filterChain = (ApplicationFilterChain) req.getFilterChain();
                if (filterChain == null) {
                    filterChain = new ApplicationFilterChain();
                    req.setFilterChain(filterChain);
                }
            }
        } else {
            // 調(diào)度程序在使用中
            filterChain = new ApplicationFilterChain();
        }

        filterChain.setServlet(servlet);
        filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());

        // 獲取過濾器上下文映射
        StandardContext context = (StandardContext) wrapper.getParent();
        FilterMap filterMaps[] = context.findFilterMaps();

        // 如果沒有過濾器映射,就認(rèn)為當(dāng)前執(zhí)行完成
        if ((filterMaps == null) || (filterMaps.length == 0))
            return (filterChain);

        // 獲取匹配的過濾器映射信息
        DispatcherType dispatcher =
                (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);

        String requestPath = null;
        Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
        if (attribute != null){
            requestPath = attribute.toString();
        }

        String servletName = wrapper.getName();

        // 將相關(guān)路徑映射的過濾器添加到此過濾器鏈中
        for (int i = 0; i < filterMaps.length; i++) {
            if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
                continue;
            }
            if (!matchFiltersURL(filterMaps[i], requestPath))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                // FIXME - log configuration problem
                continue;
            }
            filterChain.addFilter(filterConfig);
        }

        // 添加與servlet名稱匹配的篩選器
        for (int i = 0; i < filterMaps.length; i++) {
            if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
                continue;
            }
            if (!matchFiltersServlet(filterMaps[i], servletName))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                // FIXME - log configuration problem
                continue;
            }
            filterChain.addFilter(filterConfig);
        }

        // 返回完整的過濾器鏈
        return filterChain;
    }

createFilterChain 的調(diào)用

final class StandardWrapperValve extends ValveBase {
    public final void invoke(Request request, Response response) throws IOException, ServletException {
        // 省略代碼...
        // 為這個請求創(chuàng)建過濾器鏈
        ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
        // 省略代碼...
        filterChain.doFilter(request.getRequest(), response.getResponse());
    }
}

執(zhí)行流程

在StandardWrapperValue類的invoke()方法中調(diào)用ApplicationFilterChai類的createFilterChain()方法
在ApplicationFilterChai類的createFilterChain()方法中調(diào)用ApplicationFilterChain類的addFilter()方法
在ApplicationFilterChain類的addFilter()方法中給ApplicationFilterConfig數(shù)組賦值。

最后一步

doFilter()方法中最后會調(diào)用一個internalDoFilter()方法,目的就是執(zhí)行ApplicationFilterChain中的全部過濾器,從代碼中可以發(fā)現(xiàn)它調(diào)用了doFilter,而在doFilter又會調(diào)用internalDoFilter 從而使所有的Filter都得以調(diào)用

private void internalDoFilter(ServletRequest request,ServletResponse response) throws IOException, ServletException {

    // 如果存在下一個,繼續(xù)調(diào)用下一個過濾器
    if (pos < n) {
        ApplicationFilterConfig filterConfig = filters[pos++];
        try {
            Filter filter = filterConfig.getFilter();

            if (request.isAsyncSupported() && "false".equalsIgnoreCase(
                    filterConfig.getFilterDef().getAsyncSupported())) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
            }
            if( Globals.IS_SECURITY_ENABLED ) {
                final ServletRequest req = request;
                final ServletResponse res = response;
                Principal principal =
                    ((HttpServletRequest) req).getUserPrincipal();

                Object[] args = new Object[]{req, res, this};
                SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
            } else {
                // 此處調(diào)用Filter的doFilter()方法  / 而 doFilter 又會調(diào)用 internalDoFilter 直到調(diào)用完所有的過濾器
                filter.doFilter(request, response, this);
            }
        } catch (IOException | ServletException | RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            e = ExceptionUtils.unwrapInvocationTargetException(e);
            ExceptionUtils.handleThrowable(e);
            throw new ServletException(sm.getString("filterChain.filter"), e);
        }
        return;
    }

    // 從最后一個開始調(diào)用
    try {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(request);
            lastServicedResponse.set(response);
        }

        if (request.isAsyncSupported() && !servletSupportsAsync) {
            request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                    Boolean.FALSE);
        }
        // 包裝請求
        if ((request instanceof HttpServletRequest) &&
                (response instanceof HttpServletResponse) &&
                Globals.IS_SECURITY_ENABLED ) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            Principal principal =
                ((HttpServletRequest) req).getUserPrincipal();
            Object[] args = new Object[]{req, res};
            SecurityUtil.doAsPrivilege("service",
                                       servlet,
                                       classTypeUsedInService,
                                       args,
                                       principal);
        } else {
            servlet.service(request, response);
        }
    } catch (IOException | ServletException | RuntimeException e) {
        throw e;
    } catch (Throwable e) {
        e = ExceptionUtils.unwrapInvocationTargetException(e);
        ExceptionUtils.handleThrowable(e);
        throw new ServletException(sm.getString("filterChain.servlet"), e);
    } finally {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(null);
            lastServicedResponse.set(null);
        }
    }
}
總結(jié)

職責(zé)鏈模式通過建立一條鏈來組織請求的處理者,請求將沿著鏈進(jìn)行傳遞,請求發(fā)送者無須知道請求在何時、何處以及如何被處理,實(shí)現(xiàn)了請求發(fā)送者與處理者的解耦。在軟件開發(fā)中,如果遇到有多個對象可以處理同一請求時可以應(yīng)用職責(zé)鏈模式,例如在Web應(yīng)用開發(fā)中創(chuàng)建一個過濾器(Filter)鏈來對請求數(shù)據(jù)進(jìn)行過濾,在工作流系統(tǒng)中實(shí)現(xiàn)公文的分級審批等等,使用職責(zé)鏈模式可以較好地解決此類問題。

優(yōu)點(diǎn)

降低耦合度,分離了請求與處理,無須知道是哪個對象處理其請求

簡化對象的相互連接,僅保持一個指向后者的引用,而不需保持所有候選接受者的引用

擴(kuò)展容易,新增具體請求處理者,只需要在客戶端重新建鏈即可,無需破壞原代碼

缺點(diǎn)

如果請求沒有明確的接收者,那么就不能保證它一定會被處理,該請求可能一直到鏈的末端都得不到處理;一個請求也可能因職責(zé)鏈沒有被正確配置而得不到處理

較長的職責(zé)鏈,請求的處理可能涉及到多個處理對象,系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時不太方便。

如果建鏈不當(dāng),可能會造成循環(huán)調(diào)用,將導(dǎo)致系統(tǒng)陷入死循環(huán)。

金無足赤,人無完人。就像所有的設(shè)計模式一樣,有優(yōu)點(diǎn)優(yōu)缺點(diǎn),但是總的來說優(yōu)點(diǎn)必定大于缺點(diǎn)或者說缺點(diǎn)相對于優(yōu)點(diǎn)來說更可控。

說點(diǎn)什么

參考文獻(xiàn):http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter11/battcn-chain-responsibility

個人QQ:1837307557

battcn開源群(適合新手):391619659

微信公眾號:battcn(歡迎調(diào)戲)

福利

關(guān)注公眾號:battcn,回復(fù)springboot即可獲得 <2017最新spring boot 外賣實(shí)戰(zhàn)微信公眾平臺視頻教程>

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70629.html

相關(guān)文章

  • 函數(shù)式編程讓你忘記設(shè)計模式

    摘要:面向?qū)ο蟪R姷脑O(shè)計模式有策略模式模板方法觀察者模式責(zé)任鏈模式以及工廠模式,使用表達(dá)式函數(shù)式編程思維有助于避免面向?qū)ο箝_發(fā)中的那些固定代碼。 本文是一篇《Java 8實(shí)戰(zhàn)》的閱讀筆記,閱讀大約需要5分鐘。 有點(diǎn)標(biāo)題黨,但是這確實(shí)是我最近使用Lambda表達(dá)式的感受。設(shè)計模式是過去的一些好的經(jīng)驗(yàn)和套路的總結(jié),但是好的語言特性可以讓開發(fā)者不去考慮這些設(shè)計模式。面向?qū)ο蟪R姷脑O(shè)計模式有策略模式...

    or0fun 評論0 收藏0
  • 利用責(zé)任模式設(shè)計一個攔截器

    摘要:前言近期在做的攔截器功能,正好用到了責(zé)任鏈模式。通過官方圖就可以非常清楚的看出是一個責(zé)任鏈模式用責(zé)任鏈模式設(shè)計一個攔截器對于攔截器來說使用責(zé)任鏈模式再好不過了。設(shè)置攔截器到責(zé)任鏈中時通過反射將的值保存到各個攔截器中。 showImg(https://segmentfault.com/img/remote/1460000016756077?w=1733&h=1300); 前言 近期在做 ...

    dreamans 評論0 收藏0
  • 忘了再看設(shè)計模式-行為型

    摘要:推文用設(shè)計模式解構(gòu)三國是一種什么體驗(yàn)行為型設(shè)計模式一策略模式工廠模式優(yōu)化結(jié)構(gòu)狀態(tài)模式隨著狀態(tài)改變而改變行為。推文狀態(tài)機(jī)與狀態(tài)模式責(zé)任鏈模式多個對象依次處理請求前者指定后者。代理模式代理針對一個對象,為了增加控制等中介雙方都是多個,為了解耦。 策略模式 選擇使用封裝好的一系列算法,可相互替換。 類比:商店[Context]買完衣服買單[Stratege](現(xiàn)金[Concrete Stra...

    ShevaKuilin 評論0 收藏0
  • 輕松學(xué)責(zé)任模式

    摘要:設(shè)計模式責(zé)任鏈模式顧名思義,責(zé)任鏈模式為請求創(chuàng)建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發(fā)送者和接收者進(jìn)行解耦。增強(qiáng)給對象指派職責(zé)的靈活性。通過改變鏈內(nèi)的成員或者調(diào)動它們的次序,允許動態(tài)地新增或者刪除責(zé)任。 設(shè)計模式 - 責(zé)任鏈模式 顧名思義,責(zé)任鏈模式(Chain of Responsibility Pattern)為請求創(chuàng)建了一個接收者對象的鏈。這種模式給予請求的類型...

    cheukyin 評論0 收藏0
  • 一起學(xué)設(shè)計模式 - 迭代器模式

    摘要:迭代器模式屬于行為型模式的一種,提供一種方法訪問一個容器中各個元素,而又不需要暴露該對象的內(nèi)部細(xì)節(jié)。迭代器模式把在元素之間游走的責(zé)任交給迭代器,而不是聚合對象。 迭代器模式(Iterator Pattern)屬于行為型模式的一種,提供一種方法訪問一個容器中各個元素,而又不需要暴露該對象的內(nèi)部細(xì)節(jié)。 概述 迭代器模式聽起來可能感覺很陌生,但是實(shí)際上,迭代器模式是所有設(shè)計模式中最簡單也是...

    JasonZhang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<