溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

設(shè)計(jì)模式綜合實(shí)戰(zhàn)項(xiàng)目x-gen 系列三

發(fā)布時(shí)間:2020-07-17 13:33:46 來(lái)源:網(wǎng)絡(luò) 閱讀:257 作者:ronger_2719 欄目:軟件技術(shù)

1 模塊內(nèi)部實(shí)現(xiàn)

1.1 實(shí)現(xiàn)起點(diǎn)

為了讓大家更好的理解配置管理模塊的內(nèi)部實(shí)現(xiàn)架構(gòu),因此先以一個(gè)最簡(jiǎn)單的實(shí)現(xiàn)結(jié)構(gòu)為起點(diǎn),采用重構(gòu)的方式,逐步把相關(guān)的設(shè)計(jì)模式應(yīng)用進(jìn)來(lái),從簡(jiǎn)單到復(fù)雜,從而讓大家更好的看到如何選擇要使用的設(shè)計(jì)模式、如何實(shí)際應(yīng)用設(shè)計(jì)模式以及如何讓多種設(shè)計(jì)模式協(xié)同工作。

1.1.1 先就來(lái)看看實(shí)現(xiàn)配置管理的起點(diǎn),首先根據(jù)對(duì)外提供的數(shù)據(jù)結(jié)構(gòu)定義,制作出相應(yīng)的數(shù)據(jù)model來(lái)。

(1)先來(lái)看看如何描述GenConf.xml中的NeedGen,對(duì)應(yīng)的xml片斷如下:
<NeedGen id="UserGenConf" provider="XmlModuleGenConf" themeId="simple">
<Params>
<Param id="fileName">UserGenConf.xml</Param>
</Params>
</NeedGen>

根據(jù)定義可以設(shè)計(jì)出如下的數(shù)據(jù)model,代碼如下:
/
描述需要被生成模塊的注冊(cè)信息
/
publicclass NeedGenModel {
/

需要被生成模塊的標(biāo)識(shí)
/
private String id;
/
用來(lái)讀取并解析需要被生成模塊的配置文件的程序標(biāo)識(shí)
/
private String provider;
/

需要被生成模塊使用的theme
/
private String theme;
/*
需要被生成模塊需要的一些參數(shù),通常是給provider使用的
*/
private Map<String,String> mapParams = new HashMap<String,String>();

//getter/setter 省略了

}

(2)然后看看ThemeModel,會(huì)涉及到GenTypeModel,先看看GenType對(duì)應(yīng)的xml片斷,示例如下:
<GenType id="GenBusinessEbi" type="cn.javass.themes.simple.actions.GenBusinessEbiAction">
<Params>
<Param id="relativePath">business.ebi</Param>
<Param id="mbPathFile">business/Ebi.txt</Param>
<Param id="preGenFileName"></Param>
<Param id="afterGenFileName">Ebi.java</Param>
</Params>
</GenType>
那么,根據(jù)定義設(shè)計(jì)出對(duì)應(yīng)的model,示例如下:
/
主題提供的能生成的功能類型
/
publicclass GenTypeModel {
/

能生成的功能類型的標(biāo)識(shí)
/
private String id;
/
具體用來(lái)生成功能的類
/
private String genTypeClass;
/

生成功能所需要的參數(shù),key:參數(shù)標(biāo)識(shí),value:參數(shù)值
/
private Map<String,String> mapParams = new HashMap<String,String>();

//getter/setter 省略了
}

(3)接下來(lái)看看theme對(duì)應(yīng)的數(shù)據(jù)模型,根據(jù)定義設(shè)計(jì)出對(duì)應(yīng)的model,示例如下:
/
主題的數(shù)據(jù)模型
/
publicclass ThemeModel {
/

主題的標(biāo)識(shí)
/
private String id ="";
/
主題的存放位置,從GenConf傳遞過(guò)來(lái)
/
private String location = "";
/

主題提供的能生成功能的類型,key:類型的標(biāo)識(shí),value:描述生成類型的model
/
private Map<String,GenTypeModel> mapGenTypes = new HashMap<String,GenTypeModel>();
/
主題提供的輸出類型,key:輸出類型的標(biāo)識(shí),value:實(shí)現(xiàn)輸出類型的類
/
private Map<String,String> mapGenOutTypes = new HashMap<String,String>();
/

主題提供的讀取配置文件的provider,key:provider的標(biāo)識(shí),value:實(shí)現(xiàn)provider的類
/
private Map<String,String> mapProviders = new HashMap<String,String>();

//getter/setter 省略了
}
(4)接下來(lái)看看GenConfModel,綜合前面兩個(gè),示例如下:
/
x-gen核心框架配置對(duì)應(yīng)的model
/
publicclass GenConfModel {
/

描述注冊(cè)的多個(gè)需要生成的模塊model
/
private List<NeedGenModel> needGens = new ArrayList<NeedGenModel>();
/
描述注冊(cè)的多個(gè)主題的model
/
private List<ThemeModel> themes = new ArrayList<ThemeModel>();
/

通用的一些常量定義,key:常量的標(biāo)識(shí),value:常量的值
/
private Map<String,String> mapConstants = new HashMap<String,String>();

/**
 *根據(jù)theme的id來(lái)獲取相應(yīng)theme的配置數(shù)據(jù)
 *@paramthemeId
 *@return
 */
public ThemeModel getThemeById(String themeId){
   for(ThemeModel tm : themes){
       if(tm.getId().equals(themeId)){
          return tm;
       }
   }
   returnnew ThemeModel();
}

//getter/setter 省略了
}

(5)然后再看ModuleConfModel,會(huì)涉及到ExtendConfModel,先來(lái)看看ExtendConfModel對(duì)應(yīng)的xml片斷,示例如下:
<ExtendConf id="moduleName" isSingle="true">user</ExtendConf>
那么,根據(jù)定義設(shè)計(jì)出對(duì)應(yīng)的model,示例如下:
/
模塊配置中擴(kuò)展數(shù)據(jù)的model
/
publicclass ExtendConfModel {
/

擴(kuò)展數(shù)據(jù)的標(biāo)識(shí)
/
private String id="";
/
描述數(shù)據(jù)是單個(gè)值還是多個(gè)值
/
privatebooleansingle = true;
/

描述單個(gè)值
/
private String value="";
/*
描述多個(gè)值
*/
private String values[] = null;

//getter/setter 省略了
}
(6)然后來(lái)看ModuleConfModel,示例如下:
/
描述模塊配置的數(shù)據(jù)model
/
publicclass ModuleConfModel {
/

模塊標(biāo)識(shí)
/
private String moduleName = "";
/
模塊生成所使用的主題的標(biāo)識(shí)
/
private String useTheme = "";
/

模塊生成所需要的擴(kuò)展數(shù)據(jù)
/
private Map<String,ExtendConfModel> mapExtends = new HashMap<String,ExtendConfModel>();
/*
模塊需要生成的功能,key:需要生成功能的標(biāo)識(shí),value:多種輸出類型的標(biāo)識(shí)的集合
*/
private Map<String,List<String>> mapNeedGenTypes = new HashMap<String,List<String>>();

//getter/setter 省略了
}

1.2 針對(duì)前面定義的API,提供一個(gè)最基本的實(shí)現(xiàn),只需要滿足最基本的功能就可以了,需要實(shí)現(xiàn)讀取配置文件的功能,然后要有緩存配置數(shù)據(jù)的功能,最后就是實(shí)現(xiàn)API中要求的功能。

根據(jù)這些要求,可以寫(xiě)出如下的示意代碼來(lái):
/
示意實(shí)現(xiàn):初步實(shí)現(xiàn)配置管理
/
publicclass GenConfEbo implements GenConfEbi {
/

用來(lái)存放核心框架配置的model
/
private GenConfModel genConf = new GenConfModel();
/*
用來(lái)存放需要生成的每個(gè)模塊對(duì)應(yīng)的配置model
key:每個(gè)需要生成的模塊標(biāo)識(shí)
value:每個(gè)需要生成的模塊對(duì)應(yīng)的配置model
*/
private Map<String, ModuleConfModel> mapModuleConf = new HashMap<String, ModuleConfModel>();

public GenConfEbo(){
   //在這里就讀取配置數(shù)據(jù)
}

privatevoid readConf(){
   //1:獲取配置的數(shù)據(jù),比如讀取配置文件
   //為了示意簡(jiǎn)單,省略了

   //2:把獲取到的配置數(shù)據(jù)設(shè)置到屬性里面,緩存起來(lái)
}

/*以下的方法為對(duì)外接口的基本實(shí)現(xiàn),大家仔細(xì)觀察會(huì)發(fā)現(xiàn),其實(shí)只要讀取到了配置的數(shù)據(jù),
  這些實(shí)現(xiàn)基本上就是在內(nèi)存里面,進(jìn)行很簡(jiǎn)單的數(shù)據(jù)獲取存在*/
public GenConfModel getGenConf() {
   returnthis.genConf;
}
public Map<String, ModuleConfModel> getMapModuleConf() {
   returnthis.mapModuleConf;
}
public ExtendConfModel getModuleExtend(ModuleConfModel moduleConf,
       String  extendId) {
   return moduleConf.getMapExtends().get(extendId);
}
public String getThemeGenOutType(ModuleConfModel moduleConf,
       String  genOutTypeId) {
   returnthis.genConf.getThemeById(
           moduleConf.getUseTheme()).getMapGenOutTypes().get(genOutTypeId);
}
public GenTypeModel getThemeGenType(ModuleConfModel moduleConf,
       String  genTypeId) {
   returnthis.genConf.getThemeById(
           moduleConf.getUseTheme()).getMapGenTypes().get(genTypeId);
}

}

2 加入簡(jiǎn)單工廠

2.1 面臨的問(wèn)題

觀察上面的實(shí)現(xiàn),向模塊外部提供了接口,可是外部根本不知道模塊內(nèi)部的具體實(shí)現(xiàn),那么模塊外部如何來(lái)獲取一個(gè)實(shí)現(xiàn)接口的實(shí)現(xiàn)對(duì)象呢?

2.2 用簡(jiǎn)單工廠來(lái)解決

簡(jiǎn)單工廠是解決上述問(wèn)題的一個(gè)合理方案。那么先一起來(lái)回顧一下簡(jiǎn)單工廠的一些基礎(chǔ)知識(shí),然后再來(lái)看如何應(yīng)用它來(lái)解決上面的問(wèn)題。

2.2.1 簡(jiǎn)單工廠基礎(chǔ)回顧

1:模式定義
提供一個(gè)創(chuàng)建對(duì)象實(shí)例的功能,而無(wú)須關(guān)心其具體實(shí)現(xiàn)。被創(chuàng)建實(shí)例的類型可以是接口、抽象類,也可以是具體的類。

2:模式本質(zhì)
簡(jiǎn)單工廠的本質(zhì)是:選擇實(shí)現(xiàn)。

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

圖 簡(jiǎn)單工廠的結(jié)構(gòu)示意圖

4:基礎(chǔ)知識(shí)

(1)簡(jiǎn)單工廠位于對(duì)外提供接口的模

(2)簡(jiǎn)單工作的主要功能就是用來(lái)創(chuàng)建對(duì)象實(shí)例,被創(chuàng)建的對(duì)象可以是接口、抽象類或是普通的類

(3)簡(jiǎn)單工廠可以實(shí)現(xiàn)成為單例,也可以實(shí)現(xiàn)成靜態(tài)工廠

(4)簡(jiǎn)單工廠的內(nèi)部實(shí)現(xiàn),主要是做“選擇合適的實(shí)現(xiàn)”,實(shí)現(xiàn)是已經(jīng)做好的,簡(jiǎn)單工廠只是來(lái)選擇使用即可

(5)簡(jiǎn)單工廠在進(jìn)行選擇的時(shí)候,需要的參數(shù)可以從客戶端傳入、配置文件、或者是運(yùn)行期程序某個(gè)運(yùn)行結(jié)果等

(6)如果使用反射+配置文件的方式,可以寫(xiě)出通用的簡(jiǎn)單工廠

5:常見(jiàn)應(yīng)用場(chǎng)景:
通常使用簡(jiǎn)單工廠來(lái)對(duì)模塊外部提供接口對(duì)象,這樣可以有效隱藏模塊內(nèi)部實(shí)現(xiàn)。

2.2.2 使用簡(jiǎn)單工廠來(lái)解決問(wèn)題的思路

簡(jiǎn)單工廠解決這個(gè)問(wèn)題的思路就是,在配置管理模塊里面添加一個(gè)類,在這個(gè)類里面實(shí)現(xiàn)一個(gè)方法,讓這個(gè)方法來(lái)創(chuàng)建一個(gè)接口對(duì)象并返回然后把這個(gè)類提供給客戶端,讓客戶端通過(guò)調(diào)用這個(gè)類的方法來(lái)獲取接口對(duì)象。

2.2.3 核心代碼示例
制作一個(gè)簡(jiǎn)單工廠,示例如下:
publicclass GenConfFactory {
private GenConfFactory(){

}
publicstatic GenConfEbi createGenConfEbi(){
   returnnew GenConfEbo();
}

}

小結(jié)
有了對(duì)外的接口和數(shù)據(jù)對(duì)象,自然需要提供工廠,來(lái)讓外部通過(guò)工廠獲取相應(yīng)的接口對(duì)象,從而有效地隱藏內(nèi)部實(shí)現(xiàn)。
到此就把對(duì)模塊外的結(jié)構(gòu)定義好了,接下來(lái)就專心于模塊內(nèi)部的實(shí)現(xiàn)了。

本文由微信公眾號(hào)——架構(gòu)設(shè)計(jì)一起學(xué) 推出,
可點(diǎn)擊“閱讀原文“了解更多!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI