模板方法模式
一 场景
在软件开发中,有时候某个方法的执行,是按照一定的顺序来执行一系列的步骤。其中有些步骤是固定不变的,而有些步骤是可变。针对这种情况,我们可以使用一种称之为模板方法的设计模式来进行设计。
在模板方法模式中,每一个步骤所对应的就是一个基本方法,而按照一定的顺序来调用这些基本方法的方法就是模板方法。
对于模板方法模式,我们会定义一个抽象类作为父类。一般会把那些不变的基本方法放到父类中,而对于那些可变的基本方法,在父类中只做一个声明。在父类中,我们还会再定义一个模版方法,这个模版方法中会按固定顺序调用这些基本方法。
对于父类中只做声明的基本方法,我们会在各个子类中给出不同具体实现。这样的话,我们就可以在确保算法结构不变的情况下,又可以给实现不同的算法逻辑。
二 定义
模板方法模式定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以在不改变一个算法结构的情况下,重定义该算法的某些特定步骤。
三 类图
AbstractClass(抽象类):抽象类中定义了一系列的基本操作(PrimitiveOperations),这些基本操作可以是具体的方法,也可以是抽象的方法。每一个基本操作对应于算法框架中的一个步骤。
抽象类中还需要定义一个模板方法(TemplateMethod),这个模板方法给出了算法的框架。模板方法其实是将算法定义为了一系列的步骤。我们调用模板方法就是按照一定的顺序,来执行定义的一系列的基本操作。为了更好的确保模板方法的算法结构不变,我们可以将模板方法声明为final类型的方法。
ConcreteClass(具体子类):是抽象类的子类,它用于实现父类中声明的抽象方法。每一个具体子类都可以对父类特定算法给出不同的实现。
四 代码示例
我们可以用一个简单的泡茶步骤作为例子,来描述一下模版方法模式。我们泡茶的时候,第一步是先烧好开水,第二步是把茶叶放入茶杯中,第三步是把开水倒入放有茶叶的茶杯,这样就算泡好一杯茶了。而要泡绿茶,就放绿茶茶叶。要泡红茶,就放红茶茶叶。
在泡茶的过程中,第一步烧好开水和第三步把开水倒入茶杯中,在所有的泡茶步骤中都是相同的。只有第二步把茶叶放入茶杯,是根据放入不同的茶叶,就泡出了不同的茶水。
我们定义一个抽象类基类,把步骤1(烧开水)和步骤3(开水倒入茶杯中)这两个固定不变的方法,定义在抽象的基类中。而步骤2(放茶叶)这个方法是可变的,在抽象类基类中,我们将步骤2只申明一个抽象的方法,不给出具体的实现,留给不同的子类来做各种的具体实现。
在抽象类基类中,我们还要定义一个模版方法,在这个方法中固定好泡茶的步骤。这个方法最好申明为final,这样子类中就不能改成这个方法。
根据泡不同种类的茶,我们就可以定义各种不同的子类。在子类中,只需要给出步骤2(放茶叶)这个方法的具体实现即可。例如:泡绿茶只需要在步骤2的方法中,给出放入绿茶茶叶的具体实现即可。
泡红茶的子类也是一样
运行示例
运行结果
五 总结
模板方法模式是一种类行为型模式。它是基于继承的代码复用技术。模版方法模式将各子类的公共行为提取出来都到父类中,只将可变行为留给子类来实现。模板方法模式在父类定义了框架算法的模板方法,以确保通过父类来控制处理流程的逻辑顺序。模板方法模式在使得顶层逻辑框架不变的情况下,实现各不相同的算法逻辑。
优点:
- 模板方法模式是将相同行为放在父类中,而子类只负责实现不同的行为,从而去除了子类中重复的代码。
- 模板方法模式在父类中定义了模板方法,模板方法是一个算法框架,子类只负责实现细节的处理。可以保证了子类算法步骤的执行次序。
- 模板方法模式中子类是覆写了父类的基本方法,不同的子类只是提供了基本方法的不同实现,这样在更换和增加新的子类就很方便,符合单一职责原则和开闭原则。