設計模式綜合實戰項目x-gen 系列三

1 模塊內部實現

1.1 實現起點

爲了讓大家更好的理解配置管理模塊的內部實現架構,因此先以一個最簡單的實現結構爲起點,採用重構的方式,逐步把相關的設計模式應用進來,從簡單到複雜,從而讓大家更好的看到如何選擇要使用的設計模式、如何實際應用設計模式以及如何讓多種設計模式協同工作。

1.1.1 先就來看看實現配置管理的起點,首先根據對外提供的數據結構定義,製作出相應的數據model來。

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

根據定義可以設計出如下的數據model,代碼如下:
/
描述需要被生成模塊的註冊信息
/
publicclass NeedGenModel {
/

需要被生成模塊的標識
/
private String id;
/
用來讀取並解析需要被生成模塊的配置文件的程序標識
/
private String provider;
/

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

//getter/setter 省略了

}

(2)然後看看ThemeModel,會涉及到GenTypeModel,先看看GenType對應的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>
那麼,根據定義設計出對應的model,示例如下:
/
主題提供的能生成的功能類型
/
publicclass GenTypeModel {
/

能生成的功能類型的標識
/
private String id;
/
具體用來生成功能的類
/
private String genTypeClass;
/

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

//getter/setter 省略了
}

(3)接下來看看theme對應的數據模型,根據定義設計出對應的model,示例如下:
/
主題的數據模型
/
publicclass ThemeModel {
/

主題的標識
/
private String id ="";
/
主題的存放位置,從GenConf傳遞過來
/
private String location = "";
/

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

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

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

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

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

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

//getter/setter 省略了
}

(5)然後再看ModuleConfModel,會涉及到ExtendConfModel,先來看看ExtendConfModel對應的xml片斷,示例如下:
<ExtendConf id="moduleName" isSingle="true">user</ExtendConf>
那麼,根據定義設計出對應的model,示例如下:
/
模塊配置中擴展數據的model
/
publicclass ExtendConfModel {
/

擴展數據的標識
/
private String id="";
/
描述數據是單個值還是多個值
/
privatebooleansingle = true;
/

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

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

模塊標識
/
private String moduleName = "";
/
模塊生成所使用的主題的標識
/
private String useTheme = "";
/

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

//getter/setter 省略了
}

1.2 針對前面定義的API,提供一個最基本的實現,只需要滿足最基本的功能就可以了,需要實現讀取配置文件的功能,然後要有緩存配置數據的功能,最後就是實現API中要求的功能。

根據這些要求,可以寫出如下的示意代碼來:
/
示意實現:初步實現配置管理
/
publicclass GenConfEbo implements GenConfEbi {
/

用來存放核心框架配置的model
/
private GenConfModel genConf = new GenConfModel();
/*
用來存放需要生成的每個模塊對應的配置model
key:每個需要生成的模塊標識
value:每個需要生成的模塊對應的配置model
*/
private Map<String, ModuleConfModel> mapModuleConf = new HashMap<String, ModuleConfModel>();

public GenConfEbo(){
   //在這裏就讀取配置數據
}

privatevoid readConf(){
   //1:獲取配置的數據,比如讀取配置文件
   //爲了示意簡單,省略了

   //2:把獲取到的配置數據設置到屬性裏面,緩存起來
}

/*以下的方法爲對外接口的基本實現,大家仔細觀察會發現,其實只要讀取到了配置的數據,
  這些實現基本上就是在內存裏面,進行很簡單的數據獲取存在*/
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 加入簡單工廠

2.1 面臨的問題

觀察上面的實現,向模塊外部提供了接口,可是外部根本不知道模塊內部的具體實現,那麼模塊外部如何來獲取一個實現接口的實現對象呢?

2.2 用簡單工廠來解決

簡單工廠是解決上述問題的一個合理方案。那麼先一起來回顧一下簡單工廠的一些基礎知識,然後再來看如何應用它來解決上面的問題。

2.2.1 簡單工廠基礎回顧

1:模式定義
提供一個創建對象實例的功能,而無須關心其具體實現。被創建實例的類型可以是接口、抽象類,也可以是具體的類。

2:模式本質
簡單工廠的本質是:選擇實現。

3:模式結構

圖 簡單工廠的結構示意圖

4:基礎知識

(1)簡單工廠位於對外提供接口的模

(2)簡單工作的主要功能就是用來創建對象實例,被創建的對象可以是接口、抽象類或是普通的類

(3)簡單工廠可以實現成爲單例,也可以實現成靜態工廠

(4)簡單工廠的內部實現,主要是做“選擇合適的實現”,實現是已經做好的,簡單工廠只是來選擇使用即可

(5)簡單工廠在進行選擇的時候,需要的參數可以從客戶端傳入、配置文件、或者是運行期程序某個運行結果等

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

5:常見應用場景:
通常使用簡單工廠來對模塊外部提供接口對象,這樣可以有效隱藏模塊內部實現。

2.2.2 使用簡單工廠來解決問題的思路

簡單工廠解決這個問題的思路就是,在配置管理模塊裏面添加一個類,在這個類裏面實現一個方法,讓這個方法來創建一個接口對象並返回然後把這個類提供給客戶端,讓客戶端通過調用這個類的方法來獲取接口對象。

2.2.3 核心代碼示例
製作一個簡單工廠,示例如下:
publicclass GenConfFactory {
private GenConfFactory(){

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

}

小結
有了對外的接口和數據對象,自然需要提供工廠,來讓外部通過工廠獲取相應的接口對象,從而有效地隱藏內部實現。
到此就把對模塊外的結構定義好了,接下來就專心於模塊內部的實現了。

本文由微信公衆號——架構設計一起學 推出,
可點擊“閱讀原文“瞭解更多!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章