模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中去具体实现。使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
类图:
模版方法模式的结构:
模版方法模式由一个抽象类和一个(或一组)实现类通过继承结构组成,抽象类中的方法分为三种:
- 抽象方法:父类中只声明但不加以实现,而是定义好规范,然后由它的子类去实现;
- 模版方法:由抽象类声明并加以实现。模版方法调用抽象方法来完成主要的逻辑功能框架,并且,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。
- 钩子方法:由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。增加了模板方法的灵活性。
public abstract class AbstractClass {
//抽象方法,具体的实现由子类去实现
protected abstract void method1();
protected abstract int method2();
protected abstract String method3();
//钩子方法,子类可以去重写,增加灵活性,使得模板方法更加灵活
protected boolean hookMethod(){
if(condition){
return true;
}else{
return false;
}
}
//模板方法,调用抽象方法来完成主要的逻辑功能框架,不允许子类破坏其逻辑框架
public final void templateMethod(){
if(hookMethod()){
method1();
method2();
}else{
method1();
method3();
}
}
}
具体类继承抽象类,重写抽象方法,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
模版方法的优点及适用场景
容易扩展。一般来说,抽象类中的模版方法是不易反生改变的部分,而抽象方法是容易反生变化的部分,因此通过增加实现类一般可以很容易实现功能的扩展,符合开闭原则。
便于维护。对于模版方法模式来说,正是由于他们的主要逻辑相同,才使用了模版方法,假如不使用模版方法,任由这些相同的代码散乱的分布在不同的类中,维护起来是非常不方便的。
比较灵活。因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,可能稍微破坏模板方法的逻辑功能框架,所以需要设计者去均衡两者之间的关系。
在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。