收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 

交流首页 » 软件设计专版 »x-gen代码生成器配置管理3——设计模式综合项目实战 x-gen代码生成器视频教程  XML
发表人 内容
javasscc
[头像]

交流经验:
总积分:1958
级别:普通会员
注册时间: 2011-10-24
文章: 200
离线

加入组合模式

n面临的问题

  分析前面解释器模式的实现,会发现对于客户端而言,并不想要去区分到底是非终结符对象还是终结符对象,只是想要以一个统一的方式来请求解析。

  该怎么解决这个问题呢?

n
n用组合模式来解决

 

n组合模式基础回顾 
初识组合模式
n定义

  将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性 。

n结构和说明
组合模式的知识要点
n组合模式的知识要点  

1:组合模式的目的是:让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作。

2:组合模式设计的关键之处,是设计一个抽象的组件类,让它可以代表组合对象和叶子对象。

3:组合模式通常会构成对象树,理论上可以包含无数个层次

4:通常需要以对象递归的方式来访问对象树种的对象

5:使用组合模式的时候,应该更关注于透明性而非安全性

6:必要的时候,要考虑父子组件的引用关系,并避免环状引用,当然有意这样设计的除外

 

思考组合模式

n组合模式的本质  

  组合模式的本质是:统一叶子对象和组合对象

n
n何时选用组合模式

1:如果你想表示对象的部分-整体层次结构,可以选用组合模式,把整体和部分的操作统一起来,使得层次结构实现更简单,从外部来使用这个层次结构也简单。

2:如果你希望统一的使用组合结构中的所有对象,可以选用组合模式,这正是组合模式提供的主要功能

 

应用组合模式

n使用组合模式来解决问题的思路

  事实上,解释器模式本身就已经应用了组合模式来设计了,比如上面的类实现中,ReadXmlExpression就相当于组合模式的Component,而ElementExpression、ElementsExpression就相当于树枝对象,而ElementsTerminalExpression、ElementTerminalExpression、PropertyTerminalExpression、PropertysTerminalExpression就相当于树叶对象。

  对于解释器模式而言,只是负责按照抽象语法树进行解析,可是抽象语法树怎么来呢?就是谁来负责组合这棵树呢?

  那就需要我们自己来写一个解析器对象了,这个解析器对象就相当于解释器模式的客户端,在这个对象里面去组合抽象语法树。

 

n此时配置管理模块中读取XML部分的结构示意如图 

 

加入备忘录模式
n面临的问题

  在根据字符串来构建对应的抽象语法树的时候,有很多字符串前面都是一样的,这样一来,每次重复创建太浪费时间了,最好是相同字符串对应的树形对象就不用创建了,直接分析后面不同的,然后把新的部分添加到已有的这棵树里面就可以了。

  那么该怎么样来处理呢?

n
n用备忘录模式来解决

 

n备忘录模式基础回顾
初识备忘录模式
n定义

  在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态 。

n结构和说明
备忘录模式的知识要点
n备忘录模式的知识要点 

1:备忘录模式的功能,首先是在不破坏封装性的前提下,捕获一个对象的内部状态。但是要记住,备忘的目的是为了在后面需要的时候进行恢复,把对象的状态恢复到备忘录所保存的状态,这才是备忘录真正的目的。

2:备忘录对象通常都会实现窄接口,一般不考虑宽接口,而且通常会实现成为原发器对象的一个私有的静态内部类

3:管理者对象可要可不要,管理者对象只是存放备忘录对象,并不能操作备忘录对象

4:使用备忘录模式,潜在的代价就是比较耗费内存

5:备忘录模式通常会结合原型模式来使用

6:备忘录的存储方式可以多样,除了内存,还可以离线存储

 

思考备忘录模式

n备忘录模式的本质  

  备忘录模式的本质是:保存和恢复内部状态

n
n何时选用备忘录模式

1:如果必须保存一个对象在某一个时刻的全部或者部分状态,这样在以后需要的时候,可以把该对象恢复到先前的状态。可以使用备忘录模式,使用备忘录对象来封装和保存需要保存的内部状态,然后把备忘录对象保存到管理者对象里面,在需要的时候,再从管理者对象里面获取备忘录对象,来恢复对象的状态

2:如果需要保存一个对象的内部状态,但是如果用接口来让其它对象直接得到这些需要保存的状态,将会暴露对象的实现细节并破坏对象的封装性。可以使用备忘录模式,把备忘录对象实现成为原发器对象的内部类,而且还是私有的,从而保证只有原发器对象才能访问该备忘录对象。这样既保存了需要保存的状态,又不会暴露原发器对象的内部实现细节。 

 

应用备忘录模式

n使用备忘录模式来解决问题的思路

  每次在拿到一个字符串过后,先跟已有的记录进行比较,找出最大的已经解析过的字符串,那么这个长度的字符串是不需要再解析的,只需要把后面没有解析的字符串拿出来进行解析,然后把解析的对象添加到已经解析好的这个对象后头就可以了。

  这就需要每次在解析的时候,每次解析完成,就向备忘录里面添加一条记录,而每次进入的时候,根据最长能匹配的字符串,从备忘录里面获取到相应的对象,这就不用解析了。

  当然,备忘录对象还是需要实现一个窄接口,也需要实现一个备忘录管理者。这里跟标准的备忘录模式有一个小小的区别,这里是在解析器对象里面直接去备忘录管理者里面获取备忘录对象,而不是从客户端来传递,这是为了让客户端操作更方便,其实由客户端传递也是可以的。

n此时配置管理模块中读取XML部分的结构示意如图 

 

加入原型模式
n面临的问题

  当我们把备忘录模式加入过后,就需要从备忘录里面获取字符串对应的对象,也需要在解析过后,把当前解析好的对象设置到备忘录里面,这里就出现了一个新的问题?那就是这些对象如果直接设置到备忘录里面,那么大家都是指向同一个内存空间,那么当解析中操作这些对象的时候,就会影响到备忘录中的对象。

  那么该怎么解决这个问题呢?

n
n用原型模式来解决

 

n原型模式基础回顾
初识原型模式
n定义

  用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

n结构和说明
 

Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。

ConcretePrototype:实现Prototype接口的类,这些类真正实现克隆自身的功能

Client:使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例。

 

原型模式的知识要点

n原型模式的知识要点

1:原型模式的主要功能就是:通过克隆来创建新的对象实例。一般来讲,新创建出来的实例的数据是和原型实例一样的。

2:原型模式的克隆方法和new操作最明显的不同就在于:new一个对象实例,一般属性是没有值的,或者是只有默认值;如果是克隆得到的一个实例,通常属性是有值的,属性的值就是原型对象实例在克隆的时候,原型对象实例的属性的值。

3:Java中已经有了clone方法的基本实现,可以直接使用,但是只是实现了浅度克隆,如果是深度克隆,还是需要额外代码实现

4:要考虑浅度克隆和深度克隆的问题,要想深度克隆成功,必须要整个克隆所涉及的对象都要正确实现克隆方法,如果其中有一个没有正确实现克隆,那么就会导致克隆失败。

5:原型模式的重心在创建新的对象实例,克隆是实现的手段。

 

思考原型模式

n原型模式的本质  

  原型模式的本质是:克隆生成对象

 

n何时选用原型模式  

1:如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统只面向接口编程,在系统需要新的对象的时候,可以通过克隆原型来得到

2:如果需要实例化的类是在运行时刻动态指定时,可以使用原型模式,通过克隆原型来得到需要的实例 

 

应用原型模式

n使用原型模式来解决问题的思路

  分析上面的问题,发现是需要把这些对象的数据设置到备忘录里面,因此一个简单的方法就是使用原型模式,通过克隆这些对象,这样既得到一个新的对象,而值又完全是一样的,这样一来,把这个新创建的对象设置到备忘录里面,大家就互不干扰了。

  同样的道理,要从备忘录里面取出这些对象的时候,也不是直接返回备忘录里面的对象,而是重新克隆一个对象,然后返回这个新的对象,从而保证备忘数据和解析操作的数据是相互独立的。

 

加入生成器模式

n面临的问题

  现在已经实现了通过一个字符串,就能够自动创建抽象语法树,然后通过解释器去解释执行,最终获取相应的数据的功能了。

  而且这个功能是通用的,语法也是比较简洁的,基本可以满足我们的功能要求了。但是新的问题又出现了,那就是要解析一个xml,需要拼接很多很多的字符串,而这些字符串的拼接过程是十分类似的,只是最终拼接后的结果不一样,那么有没有什么好方法,来让这些字符串的拼接过程变得简单、统一呢?

n
n用生成器模式来解决

 

n生成器模式基础回顾
初识生成器模式
n定义

  将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

n结构和说明

 生成器模式的知识要点

n生成器模式的知识要点 

1:生成器模式重在解决一步一步构造复杂对象的问题,更为重要的是,这个构建的过程是统一的,固定不变的,变化的部分放到生成器部分了。

2:生成器模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用,具体的构造实现可以很方便的扩展和切换,从而可以灵活的组合来构造出不同的产品对象。

3:生成器模式一般存在两个部分,一个部分是部件构造和产品装配,另一个部分是整体构建的算法。

4:生成器模式有一种退化的情况,就是让客户端和Director融合起来,让客户端直接去操作Builder,就好像是指导者自己想要给自己构建产品一样。

5:生成器模式里面,指导者承担的是整体构建算法部分,是相对不变的部分。

6:指导者分离出去的变化部分,就到了生成器那边,每个生成器对象都可以有两部分功能,一个是创建部件对象,一个是组装部件。

7:在标准的生成器模式里面,在Builder实现里面会提供一个返回装配好的产品的方法,在Builder接口上是没有的。

8:在标准的生成器模式里面,一般是不需要对产品定义抽象接口。

 

思考生成器模式

n生成器模式的本质  

  生成器模式的本质是:分离整体构建算法和部件构造

 

n何时选用生成器模式  

1:如果创建对象的算法,应该独立于该对象的组成部分以及它们的装配方式时

2:如果同一个构建过程有着不同的表示时

 

应用生成器模式

n使用生成器模式来解决问题的思路

  每个字符串都是从根节点开始,依次拼接到最后需要取值的地方,因此可以把这个拼接的过程统一起来,做成生成器,而调用这些生成器来构建最终产品的客户端,这个时候就充当了生成器模式中的指导者。

n此时配置管理模块中读取XML部分的结构示意如图 

 


加入策略模式

n面临的问题

  现在字符串也可以通过Builder模式来拼接了,看起来一切很棒。又有一个新的问题出现了,那就是配置的数据里面有动态的内容,需要动态解析。有些朋友会说,哪里有动态的内容呢?

  由于在配置ExtendConf的值时,会发现经常需要在某一个配置里面,需要使用已经配过的一个值,这个值可能直接来之本模块其它的ExtendConf的值,也可能来自GenConf中配置的数据。因而设计了表达动态引用的语法,大致如下:

1:直接引用本模块配置的其它ExtendConf的数据,有两种方式,如果只是简单引用某一个配置的值,那么就直接写成${引用的ExtendConf的id},示例如下:

<ExtendConfs>

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

  <ExtendConf id="modulePackge" isSingle="true">cn.javass.${moduleName}</ExtendConf>

</ExtendConfs>

 

2:直接引用本模块配置的其它ExtendConf的数据,还有两种方式,x-gen支持Beanshell的脚本,并自动传入gm代表GenConfModel,mapEcms代表当前模块配置的mapExtends,那么就可以写成${mapEcms.get(“引用的ExtendConf的id”);},示例如下:

<ExtendConfs>

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

  <ExtendConf id="modulePackge" isSingle="true">cn.javass.${ mapEcms.get(“moduleName”);}</ExtendConf>

</ExtendConfs>

  当然,Beanshell脚本更多的知识,请参见Beanshell随机文档。总之现在要解析包含动态内容的配置,而且有两种基本的解析方式,一种是直接替换当前模块内的配置数据,另外一种是用Beanshell来运行配置的表达式,以获得最后的结果。那么在具体运行时,我们该到底使用哪一种方式来实现动态解析呢?

 

n用策略模式来解决  
n
n策略模式基础回顾
初识策略模式
n定义

  定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化 。

n结构和说明
策略模式的知识要点
n策略模式的知识要点 

1:策略模式的功能是把具体的算法实现,从具体的业务处理里面独立出来,把它们实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。

2:策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活、具有更好的维护性和扩展性。

3:策略模式一个很大的特点就是各个策略算法的平等性。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。

4:使用策略模式的时候,要注意谁来选择策略,可以是客户端,也可以在上下文里面。而跟策略模式类似的状态模式,一般是不会让客户端来选择状态的,状态是内部行为,这是一个很重要的区别。

5:策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态的在不同的策略实现中切换,但是同时只能使用一个。

6:上下文在策略模式里面有特殊的地位,上下文使用具体的策略实现对象,反过来,策略实现对象也可以从上下文获取所需要的数据。甚至在某些情况下,策略实现对象还可以回调上下文的方法来实现一定的功能,这种使用场景下,上下文变相充当了多个策略算法实现的公共接口,在上下文定义的方法可以当做是所有或者是部分策略算法使用的公共功能。

 

思考策略模式

n策略模式的本质  

  策略模式的本质是:分离算法,选择实现

n
n何时选用策略模式

1:出现有许多相关的类,仅仅是行为有差别的情况,可以使用策略模式来使用多个行为中的一个来配置一个类的方法,实现算法动态切换

2:出现同一个算法,有很多不同的实现的情况,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次

3:需要封装算法中,与算法相关的数据的情况,可以使用策略模式来避免暴露这些跟算法相关的数据结构

4:出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句 

 

应用策略模式

n使用策略模式来解决问题的思路

  很明显,上面描述的场景是策略模式适用的场景,两种解析动态内容的方式就是两种算法,而要判断到底该使用哪一种方式来实现动态解析,就可以在策略模式的上下文中进行就可以了。

 

n此时配置管理模块读取XML部分的结构示意如图 

 

 

  恭喜!恭喜!

  学到这里,你已经完成了配置管理模块的实现,并综合应用了9种以上的设计模式!

 

 

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


推广链接
精品视频课程推荐

Java数据结构和算法精讲版
本课程专注于数据结构和算法的内容,使用Java来进行代码示例,不空洞的讲解概念和理论,重点放在代码的实现和示例上。 从零开始、全面系统、成体系的讲解数据结构和基本算法,循序渐进的讲述构建软件系统所常见的数据结构和算法。

透彻理解JavaBean视频教程
深入浅出的讲解JavaBen的写法、JavaBean的用法、JavaBean的实现机制、JavaBean对应翻译的代码理解。

研磨设计模式——跟着cc学设计系列视频教程
本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 技术要点:如何实现可配置、如何实现缓存以及缓存的管理、如何实现用缓存来控制多实例的创建、如何实现参数化工厂、 如何实现可扩展工厂、如何实现原型管理器、如何实现Java的静态代理和动态代理、如何实现多线程处理队列请求、 如何实现命令的参数化配置、可撤销的操作、宏命令、队列请求和日志请求、如何实现翻页迭代、如何检测环状结构、 如何实现通用的增删改查、如何模拟工作流来处理流程、如何实现简单又通用的XML读取、如何实现模拟AOP的功能......

《设计模式综合项目实战》——跟着cc学设计系列精品视频教程

Ajax+JSON基础实战视频教程
数据校验、Javascript模拟多线程、下拉列表联动、操作XML、AJAX结合JSON的操作、Json-lib的使用

 
交流首页 » 软件设计专版
Message 快速回复

前往:   

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网