设计模式综合实战项目x-gen 系列三

Posted jiagoushejiyiqixue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式综合实战项目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();

    }

}

 

 小结

       有了对外的接口和数据对象,自然需要提供工厂,来让外部通过工厂获取相应的接口对象,从而有效地隐藏内部实现。

       到此就把对模块外的结构定义好了,接下来就专心于模块内部的实现了。

 

本文由微信公众号——架构设计一起学 推出,

可点击“阅读原文”选择音频版,

听CC讲解本期内容!

以上是关于设计模式综合实战项目x-gen 系列三的主要内容,如果未能解决你的问题,请参考以下文章

设计模式综和实战项目x-gen系列二

私塾在线java设计模式综合项目实战

IdentityServer4 综合应用实战系列 登录

java架构师大型分布式综合项目实战,高并发,集群,高可用,程序设计,性能优化,架构设计,负载均衡,大数据量

实战:QT车牌识别系统综合设计

IdentityServer4 综合应用实战系列 登录