成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java設(shè)計(jì)模式綜合運(yùn)用(責(zé)任鏈模式進(jìn)階)

suosuopuo / 671人閱讀

摘要:責(zé)任鏈模式的具體運(yùn)用以及原理請(qǐng)參見(jiàn)筆者責(zé)任鏈模式改進(jìn)方式引入適配器模式關(guān)于接口適配器模式原理以及使用場(chǎng)景請(qǐng)參見(jiàn)筆者適配器模式。

1 責(zé)任鏈模式現(xiàn)存缺點(diǎn)

由于責(zé)任鏈大多數(shù)都是不純的情況,本案例中,只要校驗(yàn)失敗就直接返回,不繼續(xù)處理接下去責(zé)任鏈中的其他校驗(yàn)邏輯了,故而出現(xiàn)如果某個(gè)部分邏輯是要由多個(gè)校驗(yàn)器組成一個(gè)整理的校驗(yàn)邏輯的話,則此責(zé)任鏈模式則顯現(xiàn)出了它的不足之處了。(責(zé)任鏈模式的具體運(yùn)用以及原理請(qǐng)參見(jiàn)筆者github wiki 2 責(zé)任鏈模式)

2 改進(jìn)方式 2.1 引入適配器模式

關(guān)于接口適配器模式原理以及使用場(chǎng)景請(qǐng)參見(jiàn)筆者github wiki 12 適配器模式 。

2.2 引入接口默認(rèn)方法
事例代碼請(qǐng)參見(jiàn)工程 design-patterns-business中的 defaultmethod包下的代碼。
2.2.1 概念

java8引入了一個(gè) default medthod

使用 default 關(guān)鍵字

Spring 4.2支持加載在默認(rèn)方法里聲明的bean

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

用來(lái)擴(kuò)展已有的接口,在對(duì)已有接口的使用不產(chǎn)生任何影響的情況下,添加擴(kuò)展。

比如我們已經(jīng)投入使用的接口需要拓展一個(gè)新的方法,在Java8以前,如果為一個(gè)使用的接口增加一個(gè)新方法,則我們必須在所有實(shí)現(xiàn)類中添加該方法的實(shí)現(xiàn),否則編譯會(huì)出現(xiàn)異常。如果實(shí)現(xiàn)類數(shù)量少并且我們有權(quán)限修改,可能會(huì)工作量相對(duì)較少。如果實(shí)現(xiàn)類比較多或者我們沒(méi)有權(quán)限修改實(shí)現(xiàn)類源代碼,這樣可能就比較麻煩。而默認(rèn)方法則解決了這個(gè)問(wèn)題,它提供了一個(gè)實(shí)現(xiàn),當(dāng)沒(méi)有顯示提供其他實(shí)現(xiàn)時(shí)就采用這個(gè)實(shí)現(xiàn),這樣新添加的方法將不會(huì)破壞現(xiàn)有代碼。

默認(rèn)方法的另一個(gè)優(yōu)勢(shì)是該方法是可選的,子類可以根據(jù)不同的需求Override默認(rèn)實(shí)現(xiàn)。

例如,我們定義一個(gè)集合接口,其中有增、刪、改等操作。如果我們的實(shí)現(xiàn)類90%都是以數(shù)組保存數(shù)據(jù),那么我們可以定義針對(duì)這些方法給出默認(rèn)實(shí)現(xiàn),而對(duì)于其他非數(shù)組集合或者有其他類似業(yè)務(wù),可以選擇性復(fù)寫(xiě)接口中默認(rèn)方法。

2.2.3 使用原則

”類優(yōu)先” 原則

若一個(gè)接口中定義了一個(gè)默認(rèn)方法,而另外一個(gè)父類或接口中又定義了一個(gè)同名的方法時(shí)選擇父類中的方法:如果一個(gè)父類提供了具體的實(shí)現(xiàn),那么接口中具有相同名稱和參數(shù)的默認(rèn)方法會(huì)被忽略。

接口沖突原則

如果一個(gè)父接口提供一個(gè)默認(rèn)方法,而另一個(gè)接口也提供了一個(gè)具有相同名稱和參數(shù)列表的方法(不管方法是否是默認(rèn)方法),那么必須覆蓋該方法來(lái)解決沖突。

4.3 項(xiàng)目演示 3.1 邏輯梳理

由于系統(tǒng)業(yè)務(wù)需求的變更,目前有兩種業(yè)務(wù)需求,

一種就是按照原來(lái)的文件上傳需求,上傳過(guò)程中需要校驗(yàn)操作,只要校驗(yàn)失敗了,就直接返回失敗信息,整個(gè)文件都不需要做處理了。(參見(jiàn)之前的文章 Java設(shè)計(jì)模式綜合運(yùn)用(門(mén)面+模版方法+責(zé)任鏈+策略))

另一種就是校驗(yàn)的邏輯都一樣,但是如果校驗(yàn)失敗的情況,需要繼續(xù)往下執(zhí)行,記錄一下失敗id即可,即需要把失敗的記錄也保存到數(shù)據(jù)庫(kù)中,比如約束字段不符合約束規(guī)則的情況,則把此字段置空,然后繼續(xù)執(zhí)行其他校驗(yàn)器邏輯即可。(本節(jié)需要討論的問(wèn)題)

3.2 實(shí)現(xiàn)方案

根據(jù)第2節(jié)的改進(jìn)方式可以知道,我們有兩種方式改進(jìn)以上邏輯。

3.2.1 采用適配器模式
代碼參見(jiàn)2.1版本的,地址為:https://github.com/landy8530/...

若采用適配器模式,此處我們會(huì)采用接口適配器模式。

接口需要多增加一個(gè)不用鏈?zhǔn)秸{(diào)用的校驗(yàn)方法,定義如下,

/**
 * 業(yè)務(wù)校驗(yàn)統(tǒng)一接口,增加了接口的默認(rèn)方法實(shí)現(xiàn),這樣可以更加方便且自由選擇實(shí)現(xiàn)接口的哪些方法。
 * @author landyl
 * @create 10:32 AM 05/09/2018
 * @version 2.0
 * @since 1.0
 */
public interface Validator {

    /**
     * 需要引入責(zé)任鏈的時(shí)候,則采用此方法
     * @param detail
     * @param chain
     * @return
     * @throws BusinessValidationException
     */
    String doValidate(R detail, F file, ValidatorChain chain) throws BusinessValidationException;

    /**
     * 不需要責(zé)任鏈的時(shí)候,則可以直接調(diào)用此方法的實(shí)現(xiàn)即可
     * @param detail
     * @return
     * @throws BusinessValidationException
     */
    boolean doValidate(R detail, F file) throws BusinessValidationException;
}

適配器類定義如下抽象類,

/**
 * @author: landy
 * @date: 2019/5/19 14:48
 * @description:
 */
public abstract class ValidatorAdapter implements Validator  {

    public String doValidate(RequestDetail detail, RequestFile file, ValidatorChain chain) throws BusinessValidationException {
        boolean isValid = this.doValidate(detail, file);
        //校驗(yàn)失敗了,就直接返回
        if(!isValid) {
            if(detail.getValidationResult() != null) {
                return detail.getValidationResult().getResultMsg();
            }
        }
        //否則往責(zé)任鏈中下一個(gè)校驗(yàn)器進(jìn)行處理
        return chain.doValidate(detail, file);
    }

    @Override
    public boolean doValidate(RequestDetail detail, RequestFile file) throws BusinessValidationException {
        return true;
    }
}

如此一來(lái),因?yàn)樵黾恿嗽薪涌谥械姆椒?,則需要在每個(gè)實(shí)現(xiàn)類中都增加一個(gè)實(shí)現(xiàn)方法,雖然有以上的適配器類,但是也要把之前實(shí)現(xiàn)接口改為繼承該適配器類,即 ValidatorAdapter 類。比如,

/**
 * @author landyl
 * @create 2:57 PM 05/09/2018
 */
@Component(ValidatorConstants.BEAN_NAME_CUSTOMER_IS_ACTIVE)
public class IsActiveValidator extends ValidatorAdapter {

    @Override
    public boolean doValidate(RequestDetail detail, RequestFile file) throws BusinessValidationException {
        if (StringUtils.isNotEmpty(detail.getIsActive())
                && !"0".equals(detail.getIsActive())
                && !"1".equals(detail.getIsActive())) {
            String result = "An invalid Is Active setting was provided. Accepted Value(s): 0, 1 (0 = No; 1 = Yes).";
            detail.bindValidationResult(Constants.INVALID_IS_ACTIVE,result);
            return false;
        }
        return true;
    }
}

而且,因?yàn)檫m配器類中的參數(shù)都是RequestDetailRequestFile類,故而子類可能需要做強(qiáng)制轉(zhuǎn)換操作,如:

@Component(ValidatorConstants.BEAN_NAME_CUSTOMER_BUSINESS_LINE)
public class BusinessLineValidator extends ValidatorAdapter {

    public String doValidate(RequestDetail detail, RequestFile file, ValidatorChain chain) throws BusinessValidationException {
        if(detail instanceof CustomerRequestDetail) {
            CustomerRequestDetail crd = (CustomerRequestDetail)detail;
            String result = validateBusinessLineLogic(crd);
            if(!Constants.VALID.equals(result)){
                return result;
            }
        }
        return chain.doValidate(detail,file);
    }
    ...

}

局限性比較多。

3.2.2 采用接口默認(rèn)方法
代碼參見(jiàn)2.0版本,地址為:https://github.com/landy8530/... ,后續(xù)也會(huì)merge到master版本。

接口定義如下,采用默認(rèn)方法實(shí)現(xiàn),

/**
 * 業(yè)務(wù)校驗(yàn)統(tǒng)一接口,增加了接口的默認(rèn)方法實(shí)現(xiàn),這樣可以更加方便且自由選擇實(shí)現(xiàn)接口的哪些方法。
 * @author landyl
 * @create 10:32 AM 05/09/2018
 * @version 2.0
 * @since 1.0
 */
public interface Validator {

    /**
     * 需要引入責(zé)任鏈的時(shí)候,則采用此方法
     * @param detail
     * @param chain
     * @return
     * @throws BusinessValidationException
     */
    default String doValidate(R detail, F file, ValidatorChain chain) throws BusinessValidationException {
        boolean isValid = this.doValidate(detail, file);
        //校驗(yàn)失敗了,就直接返回
        if(!isValid) {
            if(detail.getValidationResult() != null) {
                return detail.getValidationResult().getResultMsg();
            }
        }
        //否則往責(zé)任鏈中下一個(gè)校驗(yàn)器進(jìn)行處理
        return chain.doValidate(detail, file);
    }

    /**
     * 不需要責(zé)任鏈的時(shí)候,則可以直接調(diào)用此方法的實(shí)現(xiàn)即可
     * @param detail
     * @return
     * @throws BusinessValidationException
     */
    default boolean doValidate(R detail, F file) throws BusinessValidationException { return true; }

}

由此可見(jiàn),其實(shí)此處的默認(rèn)方法,就是上節(jié)中的適配器類的實(shí)現(xiàn)方式而已,而且對(duì)于后續(xù)的實(shí)現(xiàn)類而言,無(wú)須變動(dòng)(針對(duì)不需要改動(dòng)業(yè)務(wù)邏輯的類而言)。即使針對(duì)需要變動(dòng)業(yè)務(wù)邏輯的類,也只是改動(dòng)部分而已,而且不需要類型強(qiáng)制轉(zhuǎn)換操作。避免了不必要的異常出現(xiàn)。

3.2.3 方案對(duì)比

經(jīng)過(guò)以上代碼實(shí)現(xiàn)可以發(fā)現(xiàn),默認(rèn)接口實(shí)現(xiàn)有其非常明顯的優(yōu)勢(shì),即擁抱變化,擴(kuò)展已有接口,向后兼容。

3.3 邏輯測(cè)試

具體的測(cè)試代碼可以參見(jiàn)相應(yīng)版本的github單元測(cè)試代碼即可。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74578.html

相關(guān)文章

  • Java 設(shè)計(jì)模式綜合運(yùn)用(門(mén)面+模版方法+責(zé)任+策略+工廠方法)

    摘要:注解方式優(yōu)點(diǎn)使用注解方式可以極大的減少使用模版方法模式帶來(lái)的擴(kuò)展時(shí)需要繼承模版類的弊端,工廠注解的方式可以無(wú)需關(guān)心其他業(yè)務(wù)類的實(shí)現(xiàn),而且減少了類膨脹的風(fēng)險(xiǎn)。 在上一篇文章Java設(shè)計(jì)模式綜合運(yùn)用(門(mén)面+模版方法+責(zé)任鏈+策略)中,筆者寫(xiě)了一篇門(mén)面模式、模版方法、責(zé)任鏈跟策略模式的綜合運(yùn)用的事例文章,但是后來(lái)筆者發(fā)現(xiàn),在實(shí)現(xiàn)策略模式的實(shí)現(xiàn)上,發(fā)現(xiàn)了一個(gè)弊端:那就是如果在后續(xù)業(yè)務(wù)發(fā)展中,需...

    Yuanf 評(píng)論0 收藏0
  • Java設(shè)計(jì)模式綜合運(yùn)用(門(mén)面+模版方法+責(zé)任+策略)

    摘要:此案例中,門(mén)面類為,然后各個(gè)門(mén)面方法的參數(shù)均為抽象類,通過(guò)決定調(diào)用中的哪個(gè)子類。抽象類持有類的對(duì)象,并且實(shí)現(xiàn)累的一個(gè)接口是為了容器啟動(dòng)完成的時(shí)候自動(dòng)把相應(yīng)的校驗(yàn)器加入到校驗(yàn)器鏈中。 引言:很久沒(méi)有更新了,主要是工作忙。最近,工作中一個(gè)子系統(tǒng)升級(jí),把之前不易擴(kuò)展的缺點(diǎn)給改進(jìn)了一下,主要是運(yùn)用了幾個(gè)設(shè)計(jì)模式進(jìn)行稍微改造了一下。本文也同步發(fā)布至簡(jiǎn)書(shū),地址: https://www.jians...

    劉東 評(píng)論0 收藏0
  • 工廠模式管理多個(gè)以太坊solidity智能合約

    摘要:在新智能合約的構(gòu)造函數(shù)中,將引用我們的合約工廠的地址。以太坊,主要是針對(duì)工程師使用進(jìn)行區(qū)塊鏈以太坊開(kāi)發(fā)的詳解。以太坊入門(mén)教程,主要介紹智能合約與應(yīng)用開(kāi)發(fā),適合入門(mén)。這里是原文用工廠模式管理多個(gè)智能合約 我們寫(xiě)了一份小的計(jì)算合約作為Hello World。如果我們可以創(chuàng)建一個(gè)允許用戶創(chuàng)建自己的計(jì)數(shù)器的合約怎么辦? showImg(https://segmentfault.com/img/...

    leone 評(píng)論0 收藏0
  • 又被面試官問(wèn)設(shè)計(jì)模式了,我真的是

    摘要:面試官要不你來(lái)手寫(xiě)下單例模式唄候選者單例模式一般會(huì)有好幾種寫(xiě)法候選者餓漢式簡(jiǎn)單懶漢式在方法聲明時(shí)加鎖雙重檢驗(yàn)加鎖進(jìn)階懶漢式靜態(tài)內(nèi)部類優(yōu)雅懶漢式枚舉候選者所謂餓漢式指的就是還沒(méi)被用到,就直接初始化了對(duì)象。面試官:我看你的簡(jiǎn)歷寫(xiě)著熟悉常見(jiàn)的設(shè)計(jì)模式,要不你來(lái)簡(jiǎn)單聊聊你熟悉哪幾個(gè)吧?候選者:常見(jiàn)的工廠模式、代理模式、模板方法模式、責(zé)任鏈模式、單例模式、包裝設(shè)計(jì)模式、策略模式等都是有所了解的候選者:...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<