论坛首页 Java企业应用论坛

读《设计模式解析》后对Dao层的重构

浏览 10190 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-04-15  
周末用了一天时间浏览了一遍《设计模式解析》这本书,其中很多观念令人耳目一新,根据作者反复提到的两条原则:

  • 找出变化并封装之。
  • 优先使用对象聚集,而不是类继承。

我突发奇想,对以前产品中的Dao部分做个简单的修改,当然,目前只是一个简单的设想。下面是以前的设计类图:



修改后的类图如下:

  • 其实第一种方案中也实现了“找出变化并封装之”的原则,但第二种方案中对变化的把握更细致更精确。
  • 表面上看,类的继承层次和数量并没有减少,但站在Dao的角度来看,优先使用了聚集,继承层次变得简单了。“优先使用对象聚集,而不是类继承”,有时候能够减少继承层次,有时则仅仅把继承再次封装起来了,继承本身并没有什么不好,关键是使用它的方式。这正如在创建对象时使用了大量的if... else,我们也许会想到用一个工厂封装之,其实if...else并没有消失,只是跑到工厂对象里去了。
  • 第二种方案中并没有创建一个SqlDialectFactory的类供OrganizationDao使用,其实OrganizationDao本身充当了这个角色。模式的重点不在于它的标准实现,而是要灵活运用他的思想。

您认为从方案一到方案二的更改有一定道理,还是画蛇添足,甚至是弄巧成拙呢?
   发表时间:2007-04-15  
我认为这两种方案本质上是一样,DAO模式本来就是策略模式(strategy模式)的应用,方案一将具体策略的实现推迟到了子类DAO中,而方案二只不过将访问数据库的具体策略封装到子类SqlDialect中并提供给DAO调用,看起来不同,但分析下结构却是一样的。

认真想了下,可以说方案二是更为细粒度的封装,方案一的封装停留在DAO对象的粒度上,而方案二将访问数据库的不同(变化点)进行了封装,细粒度带来的好像就是代码增多,比如在方案二中,DAO、SqlDialect和子类SqlDialect的方法要保持一致。
0 请登录后投票
   发表时间:2007-04-15  
引用
我认为这两种方案本质上是一样,DAO模式本来就是策略模式(strategy模式)的应用,方案一将具体策略的实现推迟到了子类DAO中,而方案二只不过将访问数据库的具体策略封装到子类SqlDialect中并提供给DAO调用,看起来不同,但分析下结构却是一样的。

认真想了下,可以说方案二是更为细粒度的封装,方案一的封装停留在DAO对象的粒度上,而方案二将访问数据库的不同(变化点)进行了封装


这段评论很到位……

引用
细粒度带来的好像就是代码增多,比如在方案二中,DAO、SqlDialect和子类SqlDialect的方法要保持一致。

在方案二中DAO和SqlDialect的接口并不一样……
0 请登录后投票
   发表时间:2007-04-15  
图上的方法名写错了,把generate写成getnerate了。我觉得细类度可以使类的内聚性更高,也更易测试。当然,细到什么程度还是需要把握的,并非越细越好。
0 请登录后投票
   发表时间:2007-04-15  
第一个方案中,为了实现不同数据库方言,于是引入了一个dao抽象类和两个子类,子类中必然大量方法类似,都是完成相同的dao逻辑。
第二个方案中,把数据库方言实现提取到了SqlDialect,再到dao中聚合SqlDialect,这样确实更加灵活,而且dao也变得简单了。由此可见优先聚合再考虑继承的好处了。
不错不错,受教了。
0 请登录后投票
   发表时间:2007-04-15  
感觉第二种方案中在OrganizationDao中实例化 sqlDialect 不好,如果dao类多了的话,如果修改sqlDialect的实现的时候,o my god~~~
还是用factory 或者 setInterface 吧
0 请登录后投票
   发表时间:2007-04-15  
引用
第一个方案中,为了实现不同数据库方言,于是引入了一个dao抽象类和两个子类,子类中必然大量方法类似,都是完成相同的dao逻辑。
第二个方案中,把数据库方言实现提取到了SqlDialect,再到dao中聚合SqlDialect,这样确实更加灵活,而且dao也变得简单了。由此可见优先聚合再考虑继承的好处了。
不错不错,受教了。
第一种方案也不是这样啊,如果使用标准的sql则,直接写如AbstractOrganization中,因此不存在你说的这种现象.

我觉得第一种方案好,第二种有些画蛇添足.

我们的目的就是为了适应不同的数据库.

第一种方案的dao子类也是这个目的,如果使用标准的sql的放入AbstractOrganization中.这个目的已经达到.

而第二种方案也是这样一个目的,表面上是优先使用组合,但实际上不是,因为Dialect也是有一个继承层次的!

我觉得是否使用聚合需要考虑以下因素,dao的职责是否单一,因为从楼主的例子看出dao存在多职责问题,而优先使用聚合则多数是将一个拥有多职责的类的一部分或者几个部分职责移出从而聚合方式.

而楼主是强行将dao的职责分成了与具体数据库有关的和与具体数据库无关两个职责,而我觉得是一个职责.

我觉得是否采用方案二一个要考虑的因素是方案一的dao的职责是否超过一个.

个人意见
0 请登录后投票
   发表时间:2007-04-16  
我选择第二种方案的另一个原因是想以后可能使用Hibernate的Dialect包,因为Hibernate的Dialect包还没有研究,所以第二个图只是一个大概的示意……
0 请登录后投票
   发表时间:2007-04-16  
引用
我觉得是否采用方案二一个要考虑的因素是方案一的dao的职责是否超过一个.

有道理
0 请登录后投票
   发表时间:2007-04-17  
如果采用spring等框架,第一种方法中的工厂就是多余了
正如大师们预测的那样 单例 工厂等模式逐渐离我们远去
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics