探索实践之软件构建(一)

来源:互联网 发布:asp源码和php源码 编辑:程序博客网 时间:2024/06/05 04:11

慎用设计模式之模版方法

 

     这儿有此模式的生动介绍 http://blog.csdn.net/wdwgr/archive/2009/04/10/4063099.aspx。在此不多讲了。此模式在实际是最常用的之一。在设计业务流程框架时很有力。例如在成本管理或成本会计中的实际成本中,有个很重要的环节,成本分配(参见http://wiki.mbalib.com/wiki/%E6%88%90%E6%9C%AC%E5%88%86%E9%85%8D和http://www.hudong.com/wiki/%E6%88%90%E6%9C%AC%E5%88%86%E9%85%8D)在软件中就可表示为三个基本流程:buildParam()--准备参数(分配类型、财务组织、核算期间等)、doAllocate()--直接和间接费用分配等、buildResult()--构建结果,包括封装错误日志。用简化的Java代码表示,可能是这样:

 

 

构建参数和结果在基类中可以写通用一些,子类基本上不用覆盖。但是对于直接和间接费用分配的复杂活动,doAllocate()一个方法还是太粗了。于是进一步抽取一个子基类,来扩充这个行为:

 

 

 

实际业务中,可能分为材料费用分配和其它费用分配,或许其它费用分配的具体实现可能是这样:

 

 

到目前为止,这个业务流程框架基本上做得不错,如果想做出材料费用分配的功能,则也可以像OtherFeeAllocator这样实现为MaterialFeeAllocator(它们基本上有不同的业务规则检验和分配的具体表,所以分两个实现类)。但是其它费用分配与材料费用分配并不是最底层的业务现象。例如把材料费用分配更改为三个更具体的:领料出库单的、其它入库单的和成本调整单的材料分配。而且其它费用分配也不一定就是最底层的,辅助生产费用分配(参见http://wiki.mbalib.com/wiki/%E8%BE%85%E5%8A%A9%E7%94%9F%E4%BA%A7%E6%88%90%E6%9C%AC%E5%88%86%E9%85%8D,更多直白地说是受益成本对象间的消耗数量分配)就与它类似,可能复用它的业务逻辑。可能是这样:

 

 

 

可惜这时候OtherFeeAllocator并不好复用,它的相当多的可以复用的更细节的流程,用了特定于其它费用归集单的库表结构,用了硬编码;它的后来扩充功能加的一些特殊参数(例如支持辅助生产部门的)也混在其中。这全部对于同一个人来维护或开发的话,倒是还好改些:把辅助生产费用分配的子类中只要复用的,把硬编码的部分替换为更小点的模版方法,让子类来覆盖;再直接加一些子类用到的特殊参数挤入继承层次结构中.......;但是如果处于不同的组(假如业务架构组与业务开发组)的人做,则麻烦了。当这个业务流程比较复杂时(显然不止上面例子这三个方法要覆盖),工作量就大了。

为了更好地用到模版方法,作出更具扩展性、可维护性的设计,或许可以:

1、业务不停地变化,类层次可能还会被后来者增加二、三层,那么每一层的设计,需要区分硬编码及可能供复用的地方;

2、在顶层的抽象类Allocator 上实现一个分配的业务接口,例如AllocatableBusiness,抽象出粒度适中的、核心的分配流程处理过程,取一足够意义的名称和适当注释;这样当某个新分配业务要提供时,开发者能够清楚实现或继承于哪一层次、复用什么及自己要特别处理什么。

3、模版方法模式会引起程序执行流在基类与子类的方法中交叉执行,不利于调试;可以适当地支持能够不是通过继承的方式复用,而用组合;这样需把原来的业务流程框架的可访问性要规划好,对外接口也要定义好,即耦合度足够低,内聚足够高。