设计模式综合实战项目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 系列三的主要内容,如果未能解决你的问题,请参考以下文章