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

Posted

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();
}

}

小结
有了对外的接口和数据对象,自然需要提供工厂,来让外部通过工厂获取相应的接口对象,从而有效地隐藏内部实现。
到此就把对模块外的结构定义好了,接下来就专心于模块内部的实现了。

本文由微信公众号——架构设计一起学 推出,
可点击“阅读原文“了解更多!

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

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

IdentityServer4 综合应用实战系列 登录

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

IdentityServer4 综合应用实战系列 登录

C++项目三代码参考(改进版)

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