配置管理1——设计模式综合项目实战 x-gen代码生成器

配置管理模块的详细功能
n获取用户配置的数据

  配置的方式很多,要求除了框架自身提供的配置方式外,还要能支持用户自定义的配置方式。比如:框架本身提供默认的配置方式为xml配置,如果用户想使用数据库来配置,那么框架必须能够支持用户自定义一种数据库配置的方式 ,并能够很容易的加入到系统中进行使用。

 

n缓存用户配置的数据

  同一份配置数据,在运行期间会多次使用,但是获取用户配置数据的动作就只需要一次就可以了,获取过后,就缓存下来,重复使用了。

 

n对外提供接口

  让其他模块通过这些接口来获取他们需要的数据

 

配置管理模块的功能边界

n配置管理模块的功能边界

1:配置管理模块不关心被访问的数据是怎么来的,它只是按照访问方式去获取这些数据,当然不同的数据格式有不同的访问方式。

2:虽然需要支持自定义配置方式,但是需要配置的数据是一定的,只是配置的格式不同,访问这些配置数据的方式不同,但最后殊途同归,都想配置管理模块提供相应的数据。因此这个需要配置的数据项是要统一起来的。

3:配置管理模块不关心获取到的数据是什么,也不关心这些数据的含义,更不关心这些数据怎么用,它只是负责获取这些数据并保存起来。

4:配置管理模块不关心谁来使用这些数据,也不关心外部获取这些数据后如何使用,它只是负责提供这些数据而已。

 

配置管理模块的对外接口

n对外数据接口设计

  目前设计的配置分成三类,虽然配置的方式不固定,但是对于核心框架而言,有一些数据是必需要配置的,所以还是需要设计对外的数据接口。

  为了简单,这里以xml为例子来说明定义的数据结构。但是请注意,x-gen框架并不局限于使用xml作为配置的方式,同样你可以选用properties文件、数据库等其他的配置方式。

  虽然配置方式不同,需要配置的数据却是一样的,所以,你可以把这里xml描述的配置数据改成任何你希望使用的配置方式相对应的数据结构。

 

n第一类是核心框架运行需要的数据

  以xml配置为例,默认取名为GenConf.xml,在每次使用的时候根据需要修改或配置其内容。当然,为了示例简单,就不去做dtd或者schema了。 

 

 

java代码:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <GenConf>  
  3.     <NeedGens>  
  4.         <NeedGen id="UserGenConf" provider="XmlModuleGenConf" themeId="simple">  
  5.             <Params>  
  6.                 <Param id="fileName">UserGenConf.xml</Param>  
  7.             </Params>   
  8.         </NeedGen>  
  9.     </NeedGens>  
  10.     <Themes>  
  11.         <Theme id="simple">cn/javass/themes/simple</Theme>  
  12.     </Themes>  
  13.   <Constants>  
  14.         <Constant id="prePackage" value="cn.javass"></Constant>  
  15.         <Constant id="projectName" value="framework"></Constant>  
  16.     </Constants>  
  17. </GenConf>  

 

n节点说明如下:

(1)<GenConf>是根节点

(2)<NeedGens> :用来注册需要generate的模块的配置,里面可以注册很多个需要generate的模块

(3)<NeedGen> :需要generate的一个模块,属性含义如下:

  Id:需要generate的模块的标识名称或编号,必须唯一

  provider:用来获取该模块配置数据的程序的标识,该标识对应的实现类定义,在该模块使用的theme里面配置

  themeId:该模块生成的时候具体使用的theme的标识

(4)<Params>:参数,通常是根据不同的provider,提供不同的参数配置,每个参数配置都包括参数标识和具体的参数值

(5)<Param>:具体一个参数的配置,值就是参数的值,属性如下:

  Id:参数的标识名称或编号,必须唯一

(6)<Themes>:用来注册generate所需要的外部theme,可以配置多个<Theme>

(7)<Theme>:具体的描述一个theme,theme存放的具体位置,可以配置一个相对路径,配置到theme存放的根文件夹即可,属性如下:

  Id:theme的标识名称或编号,必须唯一

(8)<Constants>:常量定义,可以配置多个常量

(9)<Constant>:单个常量定义,值就是常量的值,属性为:

  id :常量的标识名称或编号,必须唯一

 

n第二类是用户需要生成的模块的配置数据

  比如:用户想要生成一个模块内的增删改查的源代码,里面有每个具体功能的配置,而每个具体功能就是一个源代码文件。

  这个也需要在每次使用的时候根据需要来配置,并注册到核心框架运行配置里面去,每次生成主要配置的就是这类数据。示例如下:

<?xml version="1.0" encoding="UTF-8"?>

<ModuleGenConf id=“UserConf”>

  <NeedGenTypes>

  <NeedGenType id="GenBusinessEbi">

  <NeedGenOutType id="File"></NeedGenOutType>

  </NeedGenType>

  </NeedGenTypes>

  <ExtendConfs>

  <ExtendConf id="moduleName" isSingle="true">user</ExtendConf>

  </ExtendConfs>

</ModuleGenConf> 

 

n节点说明如下:

(1)<ModuleGenConf>:每个模块配置的根节点,属性如下:

  id:模块的标识,不重复即可

(2)<NeedGenTypes>:用来配置需要生成的功能,可以配置多个

(3)<NeedGenType>:配置一个本模块需要生成的功能,属性如下:

  id:需要生成的功能的标识,这个标识在theme的配置中定义

(4)<NeedGenOutType>:配置模块的某个功能生成完成后,输出的类型,一个功能可以有多种输出。属性如下:

  id:具体输出的标识,这个标识在theme的配置中定义

(5)<ExtendsConfs>:本模块需要配置的,自行扩展的数据,可以配置多个数据。

(6)<ExtendConf>:描述一条自行扩展的数据,属性如下:

  id:自定义数据的标识

  isSingle:数据是单个值还是一个数组,true表示是单个值,false表示是数组,如果是数组的话,多个值之间用逗号分开

 

n第三类就是外部主题的配置数据

  在制作主题的时候就配置好,里面有这套主题需要的外部数据,和预定义好的功能配置,在每次使用的时候一般不需要配置或修改。比如:缺省为xml配置,取名为ThemeConf.xml。

  外部主题目前不支持自定义,也就是采用默认的xml方式,而且文件名称也固定是ThemeConf.xml,其实要实现支持自定义也很简单,只是没有必要,那样会无谓的增加复杂度。

  示例如下:

 

java代码:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Theme id="simple">  
  3.   <GenTypes>  
  4.     <GenType id="GenBusinessEbi" type="cn.javass.themes.simple.actions.GenBusinessEbiAction">  
  5.       <Params>  
  6.         <Param id="relativePath">business.ebi</Param>  
  7.         <Param id="mbPathFile">business/Ebi.txt</Param>  
  8.         <Param id="preGenFileName"></Param>  
  9.         <Param id="afterGenFileName">Ebi.java</Param>  
  10.       </Params>  
  11.     </GenType>  
  12.   </GenTypes>  
  13.   <GenOutTypes>  
  14.     <GenOutType id="Console" type="cn.javass.xgen.output.types.OutputToConsole"></GenOutType>  
  15.     <GenOutType id="File" type="cn.javass.xgen.output.types.OutputToFile"></GenOutType>  
  16.   </GenOutTypes>  
  17.   <Providers>  
  18.     <Provider id="XmlModuleGenConf" type="cn.javass.xgen.genconf.implementors.xmlimpl.ModuleGenConfXmlImpl"></Provider>  
  19.   </Providers>    
  20. </Theme>  

 

(1)<Theme>:主题配置的根节点,属性如下:

  id:主题的标识,必须唯一,在GenConf注册theme的id就是这个值

(2)<GenTypes>:主题提供的可输出的功能,可配置多个

(3)<GenType>:描述一个主题可输出的具体功能,属性如下:

  id:功能的标识,必须唯一,在ModuleGenConf里面配置每个模块的NeedGenType的id就是这个值

  type:真正实现输出功能的类

(4)Params:配置每个输出类需要的参数,下面可以配置多个param

(5)param:具体的每个参数的配置,值就是参数的值,属性为:

  id:参数的标识,在一个params必须唯一

(6)GenOutTypes:主题提供的输出类型,可以配置多个

(7)GenOutType:一个具体的输出类型,属性如下:

  id:功能的标识,必须唯一,在ModuleGenConf里面配置每个模块的NeedGenOutType的id就是这个值

  type:真正实现输出类型的类

(6)Providers:主题提供的读取配置文件的类型,可以配置多个

(9)Provider:一个具体的读取配置文件的类型,属性如下:

  id:功能的标识,必须唯一,在GenConf里面配置NeedGen的provider就是这个值

  type:真正实现具体的读取配置文件的类

 

n对外程序接口设计

  为了让外部获取配置管理模块内的数据,提供相应的API(应用程序接口),也就是GenConfEbi

 

配置管理模块的内部实现

 

n实现的起点

 

  为了让大家更好的理解配置管理模块的内部实现架构,因此先以一个最简单的实现结构为起点,采用重构的方式,逐步把相关的设计模式应用进来,从简单到复杂,从而让大家更好的看到如何选择要使用的设计模式、如何实际应用设计模式以及如何让多种设计模式协同工作。

 

  1:先就来看看实现配置管理的起点,首先根据对外提供的数据结构定义,制作出相应的数据model来。

 

  2:针对前面定义的API,提供一个最基本的实现,只需要满足最基本的功能就可以了,需要实现读取配置文件的功能,然后要有缓存配置数据的功能,最后就是实现API中要求的功能。

 

n此时配置管理模块的结构示意如图

加入简单工厂

n面临的问题 

  观察上面的实现,向模块外部提供了接口,可是外部根本不知道模块内部的具体实现,那么模块外部如何来获取一个实现接口的实现对象呢?

n用简单工厂来解决

  简单工厂是解决上述问题的一个合理方案。那么先一起来回顾一下简单工厂的一些基础知识,然后再来看如何应用它来解决上面的问题。

n简单工厂基础回顾 
初识简单工厂
n定义

  提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。

n结构和说明

  Api:定义客户所需要的功能接口

  Impl:具体实现Api的实现类,可能会有多个

  Factory:工厂,选择合适的实现类来创建Api接口对象

  Client:客户端,通过Factory去获取Api接口对象,然后面向Api接口编程  


简单工厂的知识要点

n简单工厂的知识要点  

1:简单工厂位于对外提供接口的模块内

2:简单工作的主要功能就是用来创建对象实例,被创建的对象可以是接口、抽象类或是普通的类

3:简单工厂可以实现成为单例,也可以实现成静态工厂

4:简单工厂的内部实现,主要是做“选择合适的实现”,实现是已经做好的,简单工厂只是来选择使用即可

5:简单工厂在进行选择的时候,需要的参数可以从客户端传入、配置文件、或者是运行期程序某个运行结果等

6:如果使用反射+配置文件的方式,可以写出通用的简单工厂

 

思考简单工厂

n简单工厂的本质  

  简单工厂的本质是:选择实现

 

n何时选用简单工厂  

1:如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无需关心具体实现

 

2:如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制

 

应用简单工厂

n 使用简单工厂来解决问题的思路  

  简单工厂解决这个问题的思路就是,在配置管理模块里面添加一个类,在这个类里面实现一个方法,让这个方法来创建一个接口对象并返回然后把这个类提供给客户端,让客户端通过调用这个类的方法来获取接口对象。

n此时配置管理模块的结构示意如图 
加入单例模式
n面临的问题 

  看看上面的基本实现,会发现一些问题:

1:如果GenConfEbo被创建多次的话,那么就会重复获取配置数据,浪费程序运行时间;

2:并且每个GenConfEbo的实例都会缓存这些数据,浪费内存空间。

3:同一个类里面,既有实现GenConfEbi要求的对外功能,又有内部实现需要的获取配置数据和缓存数据的功能,从类的设计上来说,这个类的职责太不单一了,应该分离一部分职责出去。

  因此这种实现肯定是不好的,那么怎么解决呢?

n用单例模式来解决

 

n单例模式基础回顾 

初识单例模式

n定义

  保证一个类仅有一个实例,并提供一个访问它的全局访问点。

n结构和说明

Singleton:

  负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,让外部来访问这个类的唯一实例。

 

单例模式的知识要点

n单例模式的知识要点  

1:单例模式是用来保证一个类在运行期间只会被创建一个类实例的

2:单例模式还提供了一个全局唯一访问这个类实例的访问点,通常就是那个getInstance方法

3:单例模式只关心类实例的创建问题,并不关心具体的业务功能。

4:单例模式是一个虚拟机范围内单例,不适用于集群等环境

5:单例模式的实现有很多种,除了常见的懒汉式和饿汉式外,还有利用缓存来实现、双重检查加锁的实现、Lazy initialization holder class模式、以及枚举的实现方式等

6:使用单例模式的时候要注意它的线程安全性

7:单例模式体现了延迟加载、缓存等常见的设计思想

8:单例模式是可以很容易的扩展到多实例控制的

 

思考单例模式

n单例模式的本质  

  单例模式的本质是:控制实例数目

n
n何时选用单例模式 

  当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题

 

应用单例模式

n此时配置管理模块的结构示意如图 


私塾在线原创精品课程,转载请注明私塾在线【http://sishuok.com/forum/blogPost/list/0/6789.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值