模板方法模式是一种炒鸡简单的设计模式,它基于继承的代码复用,定义一个操作中的算法框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些步骤。
我们可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。
反例
假如leader让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验设计一个类图
由这个类图可知,非常简单的实现了悍马车,该车有两个型号H1和H2。那现在我们开始实现这两个型号的悍马车,首先我们得把抽象类写好,然后两个不同的模型实现类通过简单的继承就可以实现要求。
首先看看抽象类HummerModel 的代码:
/**
* HummerModel
*
* @author xiapeng
* @version 1.0
* @description 抽象汽车动作模板
* @date 2018-10-22 14:13
*/
public abstract class HummerModel {
//发动
public abstract void start();
//停止
public abstract void stop();
//鸣笛
public abstract void alarm();
//轰鸣
public abstract void engineBoom();
//车总归要跑
public abstract void run();
}
下面我们来实现两个悍马的模型:
悍马H1型车HummerH1 :
/**
* HummerH1
*
* @author xiapeng
* @version 1.0
* @description 悍马H1型车
* @date 2018-10-22 14:16
*/
public class HummerH1 extends HummerModel {
@Override
public void start() {
System.out.println("H1发动");
}
@Override
public void stop() {
System.out.println("H1停止");
}
@Override
public void alarm() {
System.out.println("H1鸣笛");
}
@Override
public void engineBoom() {
System.out.println("H1轰鸣");
}
@Override
public void run() {
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
悍马H2型车HummerH2 :
/**
* HummerH2
*
* @author xiapeng
* @version 1.0
* @description 悍马H2型车
* @date 2018-10-22 14:16
*/
public class HummerH2 extends HummerModel {
@Override
public void start() {
System.out.println("H2发动");
}
@Override
public void stop() {
System.out.println("H2停止");
}
@Override
public void alarm() {
System.out.println("H2鸣笛");
}
@Override
public void engineBoom() {
System.out.println("H2轰鸣");
}
@Override
public void run() {
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
对比H1型车和H2型车,两种汽车的run方法执行的顺序完全相同,所以不应该出现在2个实现类中,应该是所有子类的共性封装。
示例
将run方法的实现写在抽象类里面。
/**
* HummerModel
* * @author xiapeng
* @version 1.0
* @description 抽象汽车启动模板
* @date 2018-10-22 14:13
*/
public abstract class HummerModel {
//发动
public abstract void start();
//停止
public abstract void stop();
//鸣笛
public abstract void alarm();
//轰鸣
public abstract void engineBoom();
//车总归要跑
public final void run(){
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
然后两个悍马的模型分别继承HummerModel,这样两个实现类就不用实现run方法了,可以直接拿来用,这就是模板方法模式。为了防止基类方法被恶意重写,一般模板方法都得加上final关键字
优点
- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类定义,子类负责实现
缺点
模板方法模式颠倒了我们平常的设计习惯:抽象类负责声明最抽象、最一般的事物属性和方法,实现类实现具体的事物属性和方法,在复杂的项目中可能会带来代码阅读的难度。