模板方法模式 Template Method Pattern 定义如下:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm‘s structure
先定义抽象模板类:
/**
* 抽象模板类
* 为了防止恶心操作,模板方法都会加上final关键字,不允许覆盖
*
* @author XiongNeng
* @version 1.0
* @since 13-5-22
*/
public abstract class AbstractTemplate {
// 基本方法
protected abstract void doSomething();
// 基本方法
protected abstract void doAnything();
// 模板方法
public final void templateMethod() {
// 调用基本方法,完成相关的业务逻辑
this.doSomething();
this.doAnything();
}
}
然后是实现类:
public class ConcreteClass1 extends AbstractTemplate {
@Override
protected void doSomething() {
System.out.println("class1 doSomething...");
}
@Override
protected void doAnything() {
System.out.println("class1 doAnything...");
}
}
public class ConcreteClass2 extends AbstractTemplate {
@Override
protected void doSomething() {
System.out.println("class2 doSomething...");
}
@Override
protected void doAnything() {
System.out.println("class2 doAnything...");
}
}
注意:
抽象模板中的基本方法尽量设计为protected,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected,更不要设置为public。实现类若非必要,尽量不要扩大父类中的访问权限。
模板方法的优点:
1,封装不变部分,扩展可变部分
2,提取公共部分代码,便于维护
3,抽象父类负责控制行为,而具体子类负责实现行为,相当于一个司令负责调度下面的部署作战方案,具体怎样去执行这个命令达到目的(到底是夜袭还是埋伏还是奇袭),就是下属决定的了。
模板方法的缺点:
抽象类定义了部分抽象方法,由子类实现,子类执行结果影响了父类结果,也就是子类对父类产生了影响,这在负责项目中,会给代码阅读带来一定的难度,让新手感到不适。
模板方法使用场景:
1,多个子类有公有方法,并且逻辑基本相同
2,重要、负责的算法,可以把核心算法设计为模板方法,周边的相关细节功能由子类实现
3,重构时候,模板方法是一个经常使用的模式,把相同代码抽取到父类中,然后通过钩子函数(见 模板方法模式的扩展)约束其行为
模板方法的扩展:
public abstract class AbstractTemplate {
// 基本方法
protected abstract void doSomething();
// 基本方法
protected abstract void doAnything();
// 模板方法
public final void templateMethod() {
// 调用基本方法,完成相关的业务逻辑
this.doSomething();
this.doAnything();
if (hookFlag()) {
System.out.println("----Oh yes, hookFlag...");
} else {
System.out.println("----Oh no, hookFlag...");
}
}
// 钩子方法
protected abstract boolean hookFlag();
}
public class ConcreteClass1 extends AbstractTemplate {
private boolean hookFlag;
@Override
protected void doSomething() {
System.out.println("class1 doSomething...");
}
@Override
protected void doAnything() {
System.out.println("class1 doAnything...");
}
@Override
protected boolean hookFlag() {
return hookFlag;
}
public void setHookFlag(boolean hookFlag) {
this.hookFlag = hookFlag;
}
}
外界条件的改变可以影响到模板方法的执行。我们抽象类中hookFlag()方法返回值影响了模板方法执行结果,该方法叫钩子方法。有了钩子方法模板方法才算完美。
最佳实践:
父类建立框架,子类在重写了父类部分的方法后,再调用从父类继承的方法,也就是模板方法,产生不同的结果,而这正是模板方法模式。这也可以理解为父类调用了子类的方法,你修改了子类,影响了父类的行为,曲线救国的方式实现了父类依赖子类的场景,模板方法就是这种效果。
模板方法在一些开源框架中应用非常多,它提供了一个抽象类,然后开源框架写了一堆子类。
如果你需要扩展功能,可以继承这个抽象类,然后覆写protected方法,在然后就是调用一个类似于execute的模板方法,就完成了你的扩展开放,非常容易扩展的一种模式。
本人博客已搬家,新地址为:http://yidao620c.github.io/