首先让我们看看生活之中的“模板”,在《设计模式-JAVA语言中的应用》是这样说的:“模板(Template)是指在薄片塑料板上面写字(或印字)后挖空,再使用毛笔或色笔涂满挖空的部分,就能看到纯手工而又不失工整的字样。看到模板上挖空形状,马上就知道最后会变出什么样的字,不过实际上所显示出来的字样还是要依使用的画笔的种类而定。拿黑色签字笔当画笔,成果当然就是签字笔风的字样;光是铅笔来画,得到的也就是灰黑色的铅笔字;如果用五颜六色的彩色笔,自然能创造出让人眼花缭乱的多色字样。但是,无论使用那种文具,制造出来的字样都还是脱不了模板上已经固定的形状。”这个例子想必日常生活中我们都见过吧!不过这和我们要讨论的Template Method有什么关系呢?
Template Method模式的目的:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。
看一个具体的例子,假如一个工作流由三个步骤来完成,执行的顺序为123依次执行,而每一个具体的步骤可能根据具体情况会有所不同,那麽我们制造如下的一个“薄片塑料板”: 最后让我们来看看如何制作出来不同的“字体”吧!
注意关键字final的意义,它意味其子类不能对工作步骤的顺序进行修改,对于abstract,我们可能意识到它并不像我们开始时认为的那麽无用了,这里的用法也是抽象类的真正含义之一。下面我们来造作两种不同的“笔风”:
最后让我们来看看如何制作出来不同的“字体”吧!
其实学习设计模式的难点,并不是记住这个模式的类图,或者是代码框架,重要的是理解思想,说的容易做起来就很难了,我们很难识别在具体的情况下该使用什么模式,其实我们不必为此而灰心,我们可以首先让我们的代码实现功能,然后在不影响代码功能的基础之上对代码进行重新的设计,重构为合适的模式。这样对于我们使用模式的难度就会减少了很多。
如何把自己的代码重构为模板方法模式呢?首先我们要将类似方法的框架抽象出来,并将方法框架上移至超类中,而子类只需要提供在算法的实现过程中有所区别的那些步骤。不过需要补充一下,上面的重构是基于继承的,实际应用中,我们也可以将方法框架上移至“模板类”中,通过组合来实现模板方法模式。下面就让我们实战一下吧!
看过了《深入浅出Hibernate》后,借此对其中关于借助模板模式对DAO重构总结一下,首先我们看一个在Hibernate下典型的DAO代码模板:
如果继续写下去,比如deleteUser、updateUser方法,会发现大部分的代码是没有任何变化的,只有兰颜色的部分发生了变化,似乎我们嗅到了代码里面一些不好的味道...既然他们都是一样的,那麽我们就会想到是否可以进行提取而形成一个模板呢?不过这里我们用的是基于Template与Callback的方法这样可以通过组合而不是继承的方式来使用模板,至于组合和继承的怎么选择,可以看看我的2006-10-16的日志《继承还是关联?是个问题》
下面是回调接口的定义:
这就是我们进行了重新设计后的UserDAO:
现在屏住呼吸,让我们看一看这段代码,它实现了上面代码一样的功能:
你是不是有一点惊异呢!简直太简单了,这就是Spring+Hiberbate带给我们的春天,这里并没有详细介绍如何配置上面的代码,我们只是看一下冰山一角,就已经足够见识其简单性和纯洁性了,代码只关心最重要的业务逻辑,而不用在为繁杂的异常处理和事务声明而费心了。这里Spring利用的也恰恰是Template Method模式!
不知道为什么写完这篇文章,好像对设计模式的认识清晰了一些,又好像更加模糊了,也许“道”亦有道...这其中的玄机也许只有靠每日的积累才能真正领悟吧...