原理与实现
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
经典实现
templateMethod() 函数定义为 final,是为了避免子类重写它。method1() 和 method2() 定义为 abstract, 是为了强迫子类去实现。
模版模式的作用
复用
模板模式把一个算法中不变的流程抽象到父类的模板方法 templateMethod() 中,将可变 的部分 method1()、method2() 留给子类 ContreteClass1 和 ContreteClass2 来实现。 所有的子类都可以复用父类中模板方法定义的流程代码。
拓展
SpringMVC 和 Servlet 的关系。Servlet 中定义了 doGet() doPost() 提子类实现。
类似的在 JUnit 的 TestCase 类中,runBare() 函数是模板方法,它定义了执行测试用例的 整体流程:先执行 setUp() 做些准备工作,然后执行 runTest() 运行真正的测试代码,最后 执行 tearDown() 做扫尾工作。尽管 setUp()、tearDown() 并不是抽象函数,还提供了 默认的实现,不强制子类去重新实现,但这部分也是可以在子类中定制的,所以也符合模板模式的定义。
总结
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法 模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。这里的 “算法”,我们可以理解为广义上的 “业务逻辑”,并不特指数据结构和算法中的 “算法”。这里的算法骨架就是 “模板”,包含算法骨架的方法就是 “模板方法”,这也是模板方法模式 名字的由来。
在模板模式经典的实现中,模板方法定义为 final,可以避免被子类重写。需要子类重写的 方法定义为 abstract,可以强迫子类去实现。不过,在实际项目开发中,模板模式的实现 比较灵活,以上两点都不是必须的。
模板模式有两大作用:复用和扩展。其中,复用指的是,所有的子类可以复用父类中提供的 模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修 改框架源码的情况下,基于扩展点定制化框架的功能。