"當(dāng)系統(tǒng)的每一部分都由最優(yōu)解或相對(duì)優(yōu)解組成,那么系統(tǒng)最終也將是最完美的。"

   這句話是在參加莫技術(shù)分享會(huì)上聽到的,這句話吸引我占在人群后面聽完了她的分享,確實(shí)受益良多。

   本文也旨在描述自己在項(xiàng)目演變中對(duì)一處公共處理邏輯優(yōu)化的過(guò)程,周期略長(zhǎng)最近有時(shí)間整理如下。

 

   業(yè)務(wù)系統(tǒng)數(shù)據(jù)傳遞過(guò)程中,會(huì)抽取一些公共的屬性和方法封裝為特定基類以便于后續(xù)開發(fā)進(jìn)行繼承。

   這些被抽象出來(lái)的擁有公共屬性的基類,在業(yè)務(wù)流轉(zhuǎn)過(guò)程中的賦值也應(yīng)當(dāng)進(jìn)行統(tǒng)一妥善的處理。

   大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   看到這里的小伙伴們可能心中有點(diǎn)疑惑,在業(yè)務(wù)組織 Class_A/Class_B/...將基類中基本屬性順勢(shì)填充不就可以了嗎?

   實(shí)際業(yè)務(wù)中 BaseClass 中的屬性需要根據(jù)各種不同的場(chǎng)景進(jìn)行演變和推算,你確定將這些公共推算方式放入業(yè)務(wù)邏輯中合適嗎??

   隨著系統(tǒng)擴(kuò)展繼承 BaseClass 的子類會(huì)膨脹,所有的子類都需要進(jìn)行父類基本屬性賦值,代碼看起來(lái)是不是有點(diǎn)重復(fù)?

   當(dāng)公共屬性推算方式發(fā)生變化,修改所有子類計(jì)算方式和修改公共方法,工作量孰重孰輕?

   抽取成公共方法這點(diǎn)毋庸置疑的,但怎樣高效和優(yōu)雅的書寫代碼呢?

   本文試結(jié)合實(shí)例,簡(jiǎn)述在業(yè)務(wù)流轉(zhuǎn)中對(duì)擁有公共屬性基類賦值的方法以及后續(xù)持續(xù)優(yōu)化。

   例子將省略公共屬性的判斷推算過(guò)程,實(shí)際項(xiàng)目中的公共屬性和業(yè)務(wù)對(duì)象過(guò)于復(fù)雜,自己簡(jiǎn)單抽象對(duì)象如下(關(guān)注點(diǎn)為公共屬性的賦值)。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

public class BaseStudentVO {    private String stu_id;    private String stu_name;    private Integer stu_age;    private Date stu_birthday;

    .......getter/setter
}public class PrimaryScholar extends BaseStudentVO {
     .......logicAttribute
}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   BaseStudentVO 為抽取公共屬性的基類,業(yè)務(wù)中使用的為 PrimaryScholar,業(yè)務(wù)開始流轉(zhuǎn)時(shí)需要將基類的公共屬性填充進(jìn)去。

   起初編寫函數(shù)時(shí)采用反射方式,由子類反射獲取超類并迭代超類公共方法,獲取特定 set 方法進(jìn)行調(diào)用,代碼思路如下:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 private Object setBaseAtrByReflect(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        Class superclass = clazz.getSuperclass();
        Method[] declaredMethods = superclass.getDeclaredMethods();        for (Method declaredMethod : declaredMethods) {            if (declaredMethod.getName().contains("set")) {                if (declaredMethod.getName().contains("Stu_id")) {
                    declaredMethod.invoke(instance, baseParam.get("stu_id"));                    continue;
                }                if (declaredMethod.getName().contains("Stu_name")) {
                    declaredMethod.invoke(instance, baseParam.get("stu_name"));                    continue;
                }                if (declaredMethod.getName().contains("Stu_age")) {
                    declaredMethod.invoke(instance, (Integer) baseParam.get("stu_age"));                    continue;
                }                if (declaredMethod.getName().contains("Stu_birthday")) {
                    declaredMethod.invoke(instance, (Date) baseParam.get("stu_birthday"));
                }
            }
        }        return instance;
    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   起初這種方式大概是最差的,需要強(qiáng)轉(zhuǎn)類型/隨屬性增多的的判斷/迭代超類的所有的公共方法....簡(jiǎn)直不忍直視。

   后面空閑時(shí)間采用 java 內(nèi)省重新編碼了函數(shù), java 內(nèi)省通俗來(lái)說(shuō)是 jdk 提供給程序員一種更優(yōu)雅的方式獲取 java-bean 的 getter/setter 方法。

   內(nèi)省和反射是兩碼事請(qǐng)區(qū)別對(duì)待,但毋容置疑內(nèi)省是由反射實(shí)現(xiàn),只不過(guò)代碼實(shí)現(xiàn)由 sun 公司的 java 團(tuán)隊(duì),并經(jīng)過(guò)很嚴(yán)格測(cè)試。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

  private Object setBaseAtrByIntrospect(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        Class superclass = clazz.getSuperclass();
        PropertyDescriptor propDesc;
        Method methodSetUserName;        for (Field field : superclass.getDeclaredFields()) {
            propDesc = new PropertyDescriptor(field.getName(), clazz);
            methodSetUserName = propDesc.getWriteMethod();
            methodSetUserName.invoke(instance, baseParam.get(field.getName()));
        }        return instance;
    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   采用內(nèi)省后比 assembleBaseAtrByReflect 反射時(shí)的代碼是不是清爽了很多,而且擯棄了很多難堪的地方,比如 強(qiáng)制類型轉(zhuǎn)換/隨屬性增多的判斷。

   當(dāng)后來(lái)偶然瞥見 apache.beanutil 中幾個(gè)有意思的 API 時(shí),我覺得是時(shí)候優(yōu)化下原項(xiàng)目中對(duì)應(yīng)函數(shù)的編碼。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 private Object setBaseAtrByBeanUtil(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        BeanUtils.setProperty(instance, "stu_id", baseParam.get("stu_id"));
        BeanUtils.setProperty(instance, "stu_name", baseParam.get("stu_name"));
        BeanUtils.setProperty(instance, "stu_age", baseParam.get("stu_age"));
        BeanUtils.setProperty(instance, "stu_birthday", baseParam.get("stu_birthday"));        return instance;
    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   代碼是不是簡(jiǎn)單明快了很多?看起來(lái)一目了然,而且進(jìn)行了精準(zhǔn)打擊,沒有多余迭代判斷。

   如果你反編譯 BeanUtil 中的對(duì)應(yīng)方法,你還是會(huì)找到 內(nèi)省的影子。

   最近瞅見了分層中對(duì)泛型的抽象使用,難免讓人浮想聯(lián)翩,忍不住使用泛型調(diào)整了該函數(shù)的實(shí)現(xiàn)。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 private <T extends BaseStudentVO> T setBaseAtrByGenenic(Map<String, Object> baseParam, T t) {
        t.setStu_id(baseParam.get("stu_id").toString());
        t.setStu_name(baseParam.get("stu_name").toString());
        t.setStu_age((Integer) baseParam.get("stu_age"));
        t.setStu_birthday((Date) baseParam.get("stu_birthday"));        return t;
    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

   泛型中的邊界限定很切合了該業(yè)務(wù)場(chǎng)景,使入?yún)⒎盒?t 能順暢的使用基類中的 set 方法,徹底擺脫了反射。

   反射的執(zhí)行效率偏低,早已成為不爭(zhēng)的事實(shí),使用泛型重寫后出現(xiàn)了類型強(qiáng)轉(zhuǎn)的問(wèn)題,但這已經(jīng)是最優(yōu)解了。

   從開始的反射到后面的內(nèi)省到最終的泛型,想法都是在翻看其他人的分享或擼一段實(shí)現(xiàn)時(shí)突然蹦出來(lái)。

 

作者:Orson 
出處:http://www.cnblogs.com/java-class/ 
如果,您認(rèn)為閱讀這篇博客讓您有些收獲,不妨點(diǎn)擊一下右下角的【推薦】 
如果,您希望更容易地發(fā)現(xiàn)我的新博客,不妨點(diǎn)擊一下左下角的【關(guān)注我】 
如果,您對(duì)我的博客內(nèi)容感興趣,請(qǐng)繼續(xù)關(guān)注我的后續(xù)博客,我是【Orson】 

本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段 聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。 

http://www.cnblogs.com/java-class/p/7147363.html