定义一个操做中的算法的框架,而将一些步骤的实现延迟到子类中,使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。java
使用模板方法模式制造两款汽车。定义汽车必须有的特质:可以发动,鸣笛和中止,不一样型号的汽车实现不一样。汽车生产完成后须要对汽车的质量进行检验,测试汽车的全部功能。算法
抽象汽车模型(抽象汽车类)框架
public abstract class AbstractCar { // 汽车能够发动,发动方式不一样,须要在实现类里实现 public abstract void start(); // 汽车能够鸣笛,但声音不一样,须要在实现类里实现 public abstract void alarm(); // 汽车能够熄火,中止方式也不一样,须要在实现类里实现 public abstract void stop(); // 测试汽车的质量,操做步骤同样,先测试启动,再测试喇叭,最后测试熄火 public void run() { // 发动汽车 this.start(); // 按喇叭 this.alarm(); // 中止汽车 this.stop(); } }
两种不一样型号的汽车(汽车实现类)测试
public class CarOne extends AbstractCar { // 发动C1型号的汽车 public abstract void start() { System.out.println("手摇启动C1型号的汽车"); } // C1型号的汽车鸣笛 public abstract void alarm() { System.out.println("C1型号的汽车鸣笛滴滴"); } // 中止C1型号的汽车 public abstract void stop() { System.out.println("钥匙关闭C1型号的汽车"); } } public class CarTwo extends AbstractCar { // 发动C2型号的汽车 public abstract void start() { System.out.println("电子启动C2型号的汽车"); } // C2型号的汽车鸣笛 public abstract void alarm() { System.out.println("C1型号的汽车鸣笛哔哔"); } // 中止C2型号的汽车 public abstract void stop() { System.out.println("电子关闭C1型号的汽车"); } }
测试汽车(场景类)this
public class Client { public static void main(String[] args) { CarOne carOne = new CarOne(); carOne.run(); CarTwo carTwo = new CarTwo(); carTwo.run(); } }
模板方法模式实现简单,仅仅使用了java的继承机制。以上述例子为例,其中AbstractCar叫作抽象模板,它的方法分为两类:设计
- 基本方法:由子类实现的方法,并在模板方法中被调用。
- 模板方法:数量不限,通常是一个具体的方法,也就是定义中所说的算法,它实现对基本方法的调度,完成固定的逻辑。
CarOne和CarTwo叫作具体模板,实现抽象模板所定义的基本方法。code
注意:抽象模板中的基本方法尽可能设计为
protected
类型,不须要i暴露的属性或方法尽可能不要设置为protected
类型,实现类非必要的状况,尽可能不扩大父类中的访问权限。继承
在上述造车的基础上实现,C1型车能够控制是否鸣笛,C2型车不鸣笛。钩子
扩展后的汽车抽象模型模板
public abstract class AbstractCar { // 汽车能够发动,发动方式不一样,须要在实现类里实现 protected abstract void start(); // 汽车能够鸣笛,但声音不一样,须要在实现类里实现 protected abstract void alarm(); // 汽车能够熄火,中止方式也不一样,须要在实现类里实现 protected abstract void stop(); // 测试汽车的质量,操做步骤同样,先测试启动,再测试喇叭,最后测试熄火 public final void run() { // 发动汽车 this.start(); if (this.isAlarm()) { // 按喇叭 this.alarm(); } // 中止汽车 this.stop(); } // 钩子方法,默认喇叭会响 protected boolean isAlarm() { return true; } }
扩展后的汽车实现类
public class CarOne extends AbstractCar { // C1汽车要能够鸣笛 private boolean alarmFlag = true; // 发动C1型号的汽车 protected abstract void start() { System.out.println("手摇启动C1型号的汽车"); } // C1型号的汽车鸣笛 protected abstract void alarm() { System.out.println("C1型号的汽车鸣笛滴滴"); } // 中止C1型号的汽车 protected abstract void stop() { System.out.println("钥匙关闭C1型号的汽车"); } // 是否鸣笛由驾驶员控制 public void setAlarm(boolean isAlarm) { this.isAlarm = isAlarm; } } public class CarTwo extends AbstractCar { // 发动C2型号的汽车 protected abstract void start() { System.out.println("电子启动C2型号的汽车"); } // C2型号的汽车鸣笛 protected abstract void alarm() { System.out.println("C1型号的汽车鸣笛哔哔"); } // 中止C2型号的汽车 protected abstract void stop() { System.out.println("电子关闭C1型号的汽车"); } // C2汽车不能鸣笛 protected boolean isAlarm() { return false; } }
C1汽车由驾驶员控制是否鸣笛,抽象类中的
isAlarm
方法的返回值影响了run
方法的执行结果,即外界条件的改变会影响到模板方法的执行,该方法就叫作钩子方法。