天天看点

Design Pattern - Template Method

模板方法模式(Template Method):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。该模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

使用场景:

1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

2、各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。即“重分解以一般化”,首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

3、控制子类扩展。模板方法只在特定点调用“Hook Method(钩子方法)”操作,这样就只允许在这些点进行扩展。

通用类图如下:

[img]http://dl.iteye.com/upload/attachment/423247/ee1a1c2c-1e08-3018-bf5b-0584f7fe81ef.jpg[/img]

我们这里的类图会详细一点,如下:

[img]http://dl.iteye.com/upload/attachment/423249/71b68b77-98e9-334e-8c6f-e64bbc94b96e.jpg[/img]

具体代码实现如下:

abstract class AbstractMethod {

protected abstract void method1();

protected abstract void method2();

// 模板方法,统一调用上面两个在子类中会被实现的方法,即不同的实现

public final void templateMethod() {

if (hookMethod()) {

method1();

}else {

method1();

method2();

}

}

// 钩子方法,protected权限可被子类覆盖,默认为返回true

protected boolean hookMethod() {

return true;

}

}

class ConcreteMethodA extends AbstractMethod{

protected void method1() {

System.out.println("子类 A :method1() ...");

}

protected void method2() {

System.out.println("子类 A :method2() ...");

}

}

class ConcreteMethodB extends AbstractMethod{

protected void method1() {

System.out.println("子类 B :method1() ...");

}

protected void method2() {

System.out.println("子类 B :method2() ...");

}

//覆盖钩子方法

protected boolean hookMethod() {

return false;

}

}

public class Client {

public static void main(String[] args) {

AbstractMethod methodA = new ConcreteMethodA();

methodA.templateMethod();

AbstractMethod methodB= new ConcreteMethodB();

methodB.templateMethod();

}

}

测试结果:

子类 A :method1() ...

子类 B :method1() ...

子类 B :method2() ...

至此,模板方法模式就简单地实现了,我们明白到抽象类AbstactMethod中的模板方法实际上是提供了一个外部可访问的接口,外部环境由该接口进入获得服务,而AbstractMethod类在此将子类可能提供不同服务给封装隐藏起来,即延迟了某些具体服务的细节,由其子类来负责实现。

另外,钩子方法的合理使用也可以使得模板方法模式更加灵活,不至于被templateMethod()简单地限制着,请参看上面例子的代码实现和测试结果。

继续阅读