模板方法模式
模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.
注意:本博文代码GitHub仓库
简而言之就是以下几点:
- 父类定义一个功能方法,其逻辑固定;
- 父类的功能方法中,对于具体情况分为可变部分和不可变部分;
- 子类继承父类,根据自身情况重写可变部分。
设计思路分析
针对与以上几点我们可以得出以下几点:
- 父类中定义一个不可更改的方法,确定整个方法的功能逻辑,用final关键字修饰不可更改不可重写;
- 父类对于逻辑可变部分,定义抽象方法,将该步骤延迟到子类中实现;
- 父类对于逻辑不变部分,定义具体方法,且用final关键字修饰不可更改不可重写;
- 父类可以定义某些逻辑判断方法来控制某些方法是否执行,子类可以通过重写逻辑判断方法进行对整体算法的部分修改;
模板方法类
模式类结构图:
模式的结构说明
模板方法模式包含以下主要角色:
- 抽象类(Abstract Class):主要定义算法的轮廓和框架。它由一个模板方法和若干个基本方法构成。
- 模板方法:定义算法的轮廓和骨架,确定了若干语句和基础方法的调用顺序,如本类中的templateMethod。
- 基本方法:定义模板方法中的具体某一个具体步骤,分为抽象方法,具体方法以及钩子方法。
基本方法:
- 抽象方法:在抽象类中申明,由具体子类实现。主要用于改变部分,延迟到子类实现。
- 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
- 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
- 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
Demo
AbstractClass.java
package com.frank.design.TemplateMethod.Demo;
/**
* 模板方法模式父类,用于定义所有不变的行为,从而去除子类重复代码,提高代码复用性。
* @AUTHOR:Frank
* @DATE:05/23/2019
*/
public abstract class AbstractClass {
//protected 修饰抽象方法是为了该方法不对外开发,只针对与实现类开放
protected abstract void primitiveOperation1();
protected abstract void primitiveOperation2();
protected abstract void primitiveOperation3();
// 条件判断方法,判断某个方法是否可以执行
protected boolean primitiveOperation4(){
return false;
}
protected final void primitiveOperation5(){
System.out.println("can't change method:primitiveOperation5");
}
//final 修饰是保证整体调用方法不被改动,保证逻辑的不可变性
public final void tmplateMethod(){
System.out.println("whole method start");
primitiveOperation1();
primitiveOperation2();
if(primitiveOperation4()){
primitiveOperation3();
}
primitiveOperation5();
System.out.println("whole method end");
}
}
ConcreteClassA .java
package com.frank.design.TemplateMethod.Demo;
/**
* 子类:对于父类方法的不同实现
* @AUTHOR:Frank
* @DATE:05/23/2019
*/
public class ConcreteClassA extends AbstractClass{
@Override
public void primitiveOperation1() {
System.out.println("This is ConcreteClassA's method : primitiveOperation1");
}
@Override
public void primitiveOperation2() {
System.out.println("This is ConcreteClassA's method : primitiveOperation2");
}
@Override
protected void primitiveOperation3() {
System.out.println("This is ConcreteClassA's method : primitiveOperation3");
}
}
ConcreteClassB.java
package com.frank.design.TemplateMethod.Demo;
/**
* 子类:对于父类方法的不同实现
* @AUTHOR:Frank
* @DATE:05/23/2019
*/
public class ConcreteClassB extends AbstractClass{
@Override
public void primitiveOperation1() {
System.out.println("This is ConcreteClassB's method : primitiveOperation1");
}
@Override
public void primitiveOperation2() {
System.out.println("This is ConcreteClassB's method : primitiveOperation2");
}
@Override
protected void primitiveOperation3() {
System.out.println("This is ConcreteClassB's method : primitiveOperation3");
}
@Override
protected boolean primitiveOperation4() {
return true;
}
}
总结
模板方法模式的优缺点
优点
- 通过封装不可变部分到父类中实现,子类负责实现可变部分,去除子类中重复代码。
- 父类中封装了公共代码,有助于提高代码复用性。
- 子类实现算法细节,有助于子类对于算法细节的扩展。
- 通过父类调用子类方法,子类增加拓展算法实现,符合“开放-封闭原则”。
缺点
一般来讲,抽象类会定义相关基础变量、方法,由子类负责继承实现。但是模板方法模式父类调用子类具体实现,可读性降低。
模板方法模式的适用场景
- 多个子类有共有的方法,并且逻辑基本相同。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法是一个经常使用的方法,把相同的代码抽取到父类中,然后通过构造函数约束其行为。