TEMPLATE METHOD模板方法
1、 意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
2、 适用性
在下面情况下可以使用Template Method模式
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共类中以避免代码重复。
- 控制子类扩展。模板方法只在特定点调用“hook”操作,这样就只允许在这些点进行扩展。
3、 结构
4、 参与者
AbstractClass
——定义抽象的原语操作(primitiveoperation),具体的子类将重定义它们以实现一个算法的各步骤。
——实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
ConcreteClass
——实现原语操作以完成算法中与特定子类相关的步骤。
5、 协作
ConcreteClass靠AbstractClass来实现算法中不变的步骤。
6、 效果
模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
模板方法导致一种反向的控制结构,这种结构也就是控制反转。即,父类调用子类的操作。
模板方法调用下列类型的操作:
- 具体的操作(ConcreteClass或对客户类的操作)。
- 具体的AbstractClass的操作(即,通常对子类有用的操作)。
- 原语操作(即,抽象操作)。
- 工厂方法。钩子操作(hookoperations),它提供了缺省的行为,子类可以在必要时进行扩展。一个钩子操作在缺省操作通常是一个空操作。
很重要的一点是模板方法应该指明哪些操作是钩子操作(可以被重定义)以及哪些是抽象操作(必须重定义)。要有效地重用一个抽象类,子类编写者必须明确了解哪些操作是设计为有待重定义的。子类可以通过重定义父类的操作来扩展该操作的行为,期间可显式地调用父类操作。
7、 实现
1) 尽量减少原语操作。定义模板方法的一个重要目的是尽量减少一个子类具体实现该算法时必须定义的那些原语操作的数目。需要重定义的操作越多,客户程序就越冗长。
2) 命名约定。可以给应重定义的那些操作的名字加上一个前缀以识别他们。
8、 代码示例
AbstractClass
package com.examples.pattern.templateMethod;
/**
* 定义模板方法、原语操作等抽象类
*/
public abstract class AbstractClass {
/**
* 原语操作(抽象的操作,必须要由子类提供实现)
*/
public abstract void doPrimitiveOperation1();
public abstract void doPrimitiveOperation2();
/**
* 模板方法,定义算法骨架。
*/
public final void templateMethod() {
doPrimitiveOperation1();
doPrimitiveOperation2();
}
}
ConcreteClasspackage com.examples.pattern.templateMethod;
/**
* 具体实现类,实现原语操作。
*/
public class ConcreteClass extends AbstractClass {
@Override
public void doPrimitiveOperation1() {
System.out.println("doPrimitiveOperation1");
}
@Override
public void doPrimitiveOperation2() {
System.out.println("doPrimitiveOperation2");
}
}
Client
package com.examples.pattern.templateMethod;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
AbstractClass ac = new ConcreteClass();
ac.doPrimitiveOperation1();
ac.doPrimitiveOperation2();
ac.templateMethod();
}
}
9、 相关模式
Factory Method模式常被模板方法调用。
Strategy:模板方法使用继承来改变算法的一部分。Strategy使用委托来改变整个算法。