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

資訊專欄INFORMATION COLUMN

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

Yuanf / 3020人閱讀

摘要:注解方式優(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)用(門面+模版方法+責(zé)任鏈+策略)中,筆者寫了一篇門面模式、模版方法、責(zé)任鏈跟策略模式的綜合運(yùn)用的事例文章,但是后來(lái)筆者發(fā)現(xiàn),在實(shí)現(xiàn)策略模式的實(shí)現(xiàn)上,發(fā)現(xiàn)了一個(gè)弊端:那就是如果在后續(xù)業(yè)務(wù)發(fā)展中,需要再次增加一個(gè)業(yè)務(wù)策略的時(shí)候,則需要再次繼承AbstractValidatorHandler類(詳情請(qǐng)參見上篇文章),這樣就會(huì)造成一定的類膨脹。今天我利用注解的方式改造成動(dòng)態(tài)策略模式,這樣就只需要關(guān)注自己的業(yè)務(wù)類即可,無(wú)需再實(shí)現(xiàn)一個(gè)類似的Handler類。
本文也同步發(fā)布至簡(jiǎn)書,地址:https://www.jianshu.com/p/b86...
1. 項(xiàng)目背景 1.1 項(xiàng)目簡(jiǎn)介

在公司的一個(gè)業(yè)務(wù)系統(tǒng)中,有這樣的一個(gè)需求,就是根據(jù)不同的業(yè)務(wù)流程,可以根據(jù)不同的組合主鍵策略進(jìn)行動(dòng)態(tài)的數(shù)據(jù)業(yè)務(wù)查詢操作。在本文中,我假設(shè)有這樣兩種業(yè)務(wù),客戶信息查詢和訂單信息查詢,對(duì)應(yīng)以下枚舉類:

/**
 * 業(yè)務(wù)流程枚舉
 * @author landyl
 * @create 11:18 AM 05/07/2018
 */
public enum WorkflowEnum {
    ORDER(2),
    CUSTOMER(3),
    ;
    ....
}

每種業(yè)務(wù)類型都有自己的組合主鍵查詢規(guī)則,并且有自己的查詢優(yōu)先級(jí),比如客戶信息查詢有以下策略:

customerId

requestId

birthDate+firstName

以上僅是假設(shè)性操作,實(shí)際業(yè)務(wù)規(guī)則比這復(fù)雜的多

1.2 流程梳理

主要業(yè)務(wù)流程,可以參照以下簡(jiǎn)單的業(yè)務(wù)流程圖。

1.2.1 查詢抽象模型

1.2.2 組合主鍵查詢策略

1.2.3 組合主鍵查詢責(zé)任鏈

2. Java注解簡(jiǎn)介

注解的語(yǔ)法比較簡(jiǎn)單,除了@符號(hào)的使用之外,它基本與Java固有語(yǔ)法一致。

2.1 元注解

JDK1.5提供了4種標(biāo)準(zhǔn)元注解,專門負(fù)責(zé)新注解的創(chuàng)建。

注解 說明
@Target 表示該注解可以用于什么地方,可能的ElementType參數(shù)有:
CONSTRUCTOR:構(gòu)造器的聲明
FIELD:域聲明(包括enum實(shí)例)
LOCAL_VARIABLE:局部變量聲明
METHOD:方法聲明
ACKAGE:包聲明
PARAMETER:參數(shù)聲明
TYPE:類、接口(包括注解類型)或enum聲明
@Retention 表示需要在什么級(jí)別保存該注解信息??蛇x的RetentionPolicy參數(shù)包括:
SOURCE:注解將被編譯器丟棄
CLASS:注解在class文件中可用,但會(huì)被VM丟棄
RUNTIME:JVM將在運(yùn)行期間保留注解,因此可以通過反射機(jī)制讀取注解的信息。
@Document 將注解包含在Javadoc中
@Inherited 允許子類繼承父類中的注解
2.2 自定義注解

定義一個(gè)注解的方式相當(dāng)簡(jiǎn)單,如下代碼所示:

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
//使用@interface關(guān)鍵字定義注解
public @interface Description {
    /*
     * 注解方法的定義(其實(shí)在注解中也可以看做成員變量)有如下的規(guī)定:
     * 1.不能有參數(shù)和拋出異常
     * 2.方法返回類型只能為八種基本數(shù)據(jù)類型和字符串,枚舉和注解以及這些類型構(gòu)成的數(shù)組
     * 3.可以包含默認(rèn)值,通過default實(shí)現(xiàn)
     * 4.如果只有一個(gè)方法(成員變量),最好命名為value
     */
    String value();
    int count() default 1; //默認(rèn)值為1
}

注解的可用的類型包括以下幾種:所有基本類型、String、Class、enum、Annotation、以上類型的數(shù)組形式。元素不能有不確定的值,即要么有默認(rèn)值,要么在使用注解的時(shí)候提供元素的值。而且元素不能使用null作為默認(rèn)值。注解在只有一個(gè)元素且該元素的名稱是value的情況下,在使用注解的時(shí)候可以省略“value=”,直接寫需要的值即可。

2.3 使用注解

如上所示的注解使用如下:

/**
 * @author landyl
 * @create 2018-01-12:39 PM
 */
//在類上使用定義的Description注解
@Description(value="class annotation",count=2)
public class Person {
    private String name;
    private int age;

    //在方法上使用定義的Description注解
    @Description(value="method annotation",count=3)
    public String speak() {
        return "speaking...";
    }
}

使用注解最主要的部分在于對(duì)注解的處理,那么就會(huì)涉及到注解處理器。從原理上講,注解處理器就是通過反射機(jī)制獲取被檢查方法上的注解信息,然后根據(jù)注解元素的值進(jìn)行特定的處理。

/**
 * @author landyl
 * @create 2018-01-12:35 PM
 * 注解解析類
 */
public class ParseAnnotation {
    public static void main(String[] args){
        //使用類加載器加載類
        try {
            Class c = Class.forName("com.annatation.Person");//加載使用了定義注解的類
            //找到類上的注解
            boolean isExist = c.isAnnotationPresent(Description.class);
            if(isExist){
                //拿到注解示例
                Description d = (Description)c.getAnnotation(Description.class);
                System.out.println(d.value());
            }
            //找到方法上的注解
            Method[] ms = c.getMethods();
            for(Method m : ms){
                boolean isMExist = m.isAnnotationPresent(Description.class);
                if(isMExist){
                    Description d = m.getAnnotation(Description.class);
                    System.out.println(d.value());
                }
            }
            //另外一種注解方式
            for(Method m:ms){
                Annotation[] as = m.getAnnotations();
                for(Annotation a:as){
                    if(a instanceof Description){
                        Description d = (Description)a;
                        System.out.println(d.value());
                    }
                }

            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
3. 策略模式升級(jí)版 3.1 策略模式實(shí)現(xiàn)方式

使用工廠進(jìn)行簡(jiǎn)單的封裝

使用注解動(dòng)態(tài)配置策略

使用模版方法模式配置策略(參見Java設(shè)計(jì)模式綜合運(yùn)用(門面+模版方法+責(zé)任鏈+策略))

使用工廠+注解方式動(dòng)態(tài)配置策略(利用Spring加載)

其中第1、2點(diǎn)請(qǐng)參見org.landy.strategy 包下的demo事例即可,而第4點(diǎn)的方式其實(shí)就是結(jié)合第1、2、3點(diǎn)的優(yōu)點(diǎn)進(jìn)行整合的方式。

3.2 注解方式優(yōu)點(diǎn)

使用注解方式可以極大的減少使用模版方法模式帶來(lái)的擴(kuò)展時(shí)需要繼承模版類的弊端,工廠+注解的方式可以無(wú)需關(guān)心其他業(yè)務(wù)類的實(shí)現(xiàn),而且減少了類膨脹的風(fēng)險(xiǎn)。

3.3 組合主鍵查詢策略

本文以組合主鍵查詢策略這一策略進(jìn)行說明,策略注解如下:

/**
 * 組合主鍵查詢策略(根據(jù)不同業(yè)務(wù)流程區(qū)分組合主鍵查詢策略,并且每個(gè)業(yè)務(wù)流程都有自己的優(yōu)先級(jí)策略)
 * @author landyl
 * @create 2:22 PM 09/29/2018
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface KeyIdentificationStrategy {

    /**
     * 主鍵策略優(yōu)先級(jí)
     * @return
     */
    int priority() default 0;
    /**
     * 業(yè)務(wù)流程類型(如:訂單信息,會(huì)員信息等業(yè)務(wù)流程)
     * @return
     */
    WorkflowEnum workflowId();
    /**
     * the spring bean name
     * @return
     */
    String beanName();

}
3.4 策略工廠

既然定義了組合主鍵查詢策略注解,那必然需要一個(gè)注解處理器進(jìn)行解析注解的操作,本文以工廠的方式進(jìn)行。主要邏輯如下:

掃描指定包下的Java類,找出相應(yīng)接口(即KeyIdentification)下的所有Class對(duì)象。

private List> getIdentifications() {
        Set packageNames = this.getBasePackages();
        List> identifications = new ArrayList<>();
        if(packageNames != null) {
            packageNames.forEach((packageName) -> identifications.addAll(getIdentifications(packageName)));
        }
        return identifications;
    }

解析注解KeyIdentificationStrategy,定義一個(gè)排序?qū)ο螅?b>KeyIdentificationComparator),指定優(yōu)先級(jí)。

/**
     * define a comparator of the KeyIdentification object through the priority of the IdentifyPriority for sort purpose.

    */

private class KeyIdentificationComparator implements Comparator {

   @Override
   public int compare(Object objClass1, Object objClass2) {
       if(objClass1 != null && objClass2 != null) {
           Optional strategyOptional1 = getPrimaryKeyIdentificationStrategy((Class)objClass1);
           Optional strategyOptional2 = getPrimaryKeyIdentificationStrategy((Class)objClass2);

           KeyIdentificationStrategy ip1 = strategyOptional1.get();
           KeyIdentificationStrategy ip2 = strategyOptional2.get();

           Integer priority1 = ip1.priority();
           Integer priority2 = ip2.priority();

           WorkflowEnum workflow1 = ip1.workflowId();
           WorkflowEnum workflow2 = ip2.workflowId();
           //先按業(yè)務(wù)類型排序
           int result = workflow1.getValue() - workflow2.getValue();
           //再按優(yōu)先級(jí)排序
           if(result == 0) return priority1.compareTo(priority2);

           return result;
       }
       return 0;
   }

}

3. 根據(jù)注解,把相應(yīng)業(yè)務(wù)類型的組合主鍵查詢策略對(duì)象放入容器中(即`DefaultKeyIdentificationChain`)。

KeyIdentificationStrategy strategy = strategyOptional.get();

               String beanName = strategy.beanName();
               //業(yè)務(wù)流程類型
               WorkflowEnum workflowId = strategy.workflowId();
               KeyIdentificationStrategy priority = getPrimaryKeyIdentificationStrategy(v).get();
               LOGGER.info("To add identification:{},spring bean name is:{},the identify priority is:{},workflowId:{}",simpleName,beanName,priority.priority(),workflowId.name());
               KeyIdentification instance = ApplicationUtil.getApplicationContext().getBean(beanName,v);

defaultKeyIdentificationChain.addIdentification(instance,workflowId);

4. 后續(xù),在各自對(duì)應(yīng)的業(yè)務(wù)查詢組件對(duì)象中即可使用該工廠對(duì)象調(diào)用如下方法,即可進(jìn)行相應(yīng)的查詢操作。

public IdentificationResultType identify(IdentifyCriterion identifyCriterion,WorkflowEnum workflowId) {

    //must set the current workflowId
    defaultKeyIdentificationChain.doClearIdentificationIndex(workflowId);
    return defaultKeyIdentificationChain.doIdentify(identifyCriterion,workflowId);
}
## 4. 總結(jié)

以上就是本人在實(shí)際工作中,對(duì)第一階段使用到的設(shè)計(jì)模式的一種反思后得到的優(yōu)化結(jié)果,可能還有各種不足,但是個(gè)人感覺還是有改進(jìn),希望大家也不吝賜教,大家一起進(jìn)步才是真理。

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

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

相關(guān)文章

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

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

    劉東 評(píng)論0 收藏0
  • Java設(shè)計(jì)模式綜合運(yùn)用(責(zé)任模式進(jìn)階)

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

    suosuopuo 評(píng)論0 收藏0
  • J2EE下的常用設(shè)計(jì)模式

    摘要:當(dāng)然,除了讓我們顯得更加專業(yè)之外,在自己所學(xué)習(xí)或者工作的項(xiàng)目中,適當(dāng)合理的使用設(shè)計(jì)模式,能夠給項(xiàng)目帶來(lái)很大的好處。 簡(jiǎn)單說兩句 本文首發(fā)公眾號(hào)【一名打字員】 對(duì)不住各位老鐵了,年前說好要更幾波JAVA的東西,又偷懶了,沒辦法,在這里用小錘錘偷偷錘了自己幾下。由于工作原因,更新時(shí)間不定,各位老鐵有問題可以私聊我哈。 對(duì)于初學(xué)者或者是正在向中高級(jí)的Java程序猿(打字員)來(lái)說,時(shí)刻梳理自己...

    robin 評(píng)論0 收藏0
  • “大話”設(shè)計(jì)模式

    摘要:抽象工廠模式是為了處理對(duì)象具有等級(jí)結(jié)構(gòu)以及對(duì)象族的問題。單例設(shè)計(jì)模式單例模式確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類成為單例類。 導(dǎo)語(yǔ):設(shè)計(jì)模式是無(wú)數(shù)碼農(nóng)前人在實(shí)際的生產(chǎn)項(xiàng)目中經(jīng)過不斷的踩坑、爬坑、修坑的經(jīng)歷總結(jié)出來(lái)的經(jīng)驗(yàn)教訓(xùn),經(jīng)過抽象之后表達(dá)成的概念。能夠幫助后來(lái)的設(shè)計(jì)者避免重復(fù)同樣的錯(cuò)誤或者彎路。我也抽空整理了一下設(shè)計(jì)模式,用自己的話總結(jié)了一下,自認(rèn)...

    coordinate35 評(píng)論0 收藏0
  • 設(shè)計(jì)模式

    摘要:建議參看學(xué)習(xí)創(chuàng)建型模式工廠模式抽象工廠模式單例模式建造者模式原型模式結(jié)構(gòu)型模式適配器模式接口轉(zhuǎn)換橋接模式過濾器模式組合模式裝飾器模式外觀模式門面模式前臺(tái)接待享元模式代理模式行為型模式責(zé)任鏈模式工作流命令模式解釋器模式 建議參看github學(xué)習(xí) 1.創(chuàng)建型模式(creational) 工廠模式(factory)抽象工廠模式(abstract factory)單例模式(singleton)...

    pekonchan 評(píng)論0 收藏0

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

0條評(píng)論

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