定义了算法的基本骨架,把一些步骤的实现延迟到子类中进行,它可以让子类不改变基本算法的数据结构而优化或者精加工( refine )某个特定的算法步骤。
模板方法设计模式有如下优点:
1) 减少了冗余的代码,重用代码部分通过父类完成
2) 将某个特定的算法步骤延迟到子类实现,不会影响父类的功能
3) 易于扩展,子类通过实现某个特定的方法而形成自己特定的算法逻辑,易于扩展
4) 子类不能修改父类算法的执行顺序
以 JUnit 为例, JUnit 的基础核心类 TestCase 使用到这种模式, TestCase 要求先运行 SetUp 方法,再运行子类中的各个 Test 方法,最后进行资源的释放。下例中的 testBare 方法,包含了算法的基本骨架: setUp,runTest 和 tearDown ,而 setUp 和 tearDown 没有实现任何逻辑,留给子类实现。因此再次总结,模板方法设计模式最大的好处是避免了代码的冗余,并且不会改变算法的基本步骤,只是对某个特定步骤的实现留给子类去完成。
/**
* Runs the bare test sequence.
* @exception Throwable if any exception is thrown
*/
public void runBare() throws Throwable {
Throwable exception= null ;
setUp();
try {
runTest();
} catch (Throwable running) {
exception= running;
}
finally {
try {
tearDown();
} catch (Throwable tearingDown) {
if (exception == null ) exception= tearingDown;
}
}
if (exception != null ) throw exception;
}
protected void runTest() throws Throwable {
assertNotNull ( fName ); // Some VMs crash when calling getMethod(null,null);
Method runMethod= null ;
try {
// use getMethod to get all public inherited
// methods. getDeclaredMethods returns all
// methods of this class but excludes the
// inherited ones.
runMethod= getClass().getMethod( fName , (Class[]) null );
} catch (NoSuchMethodException e) {
fail ( "Method \"" + fName + "\" not found" );
}
if (!Modifier.isPublic (runMethod.getModifiers())) {
fail ( "Method \"" + fName + "\" should be public" );
}
try {
runMethod.invoke( this , (Object[]) new Class[0]);
}
catch (InvocationTargetException e) {
e.fillInStackTrace();
throw e.getTargetException();
}
catch (IllegalAccessException e) {
e.fillInStackTrace();
throw e;
}
}
/**
* Sets up the fixture, for example, open a network connection.
* This method is called before a test is executed.
*/
protected void setUp () throws Exception {
}
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*/
protected void tearDown() throws Exception {
}