模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
我们先炒两个菜
/**
* 炒个西红柿
* @author aodeng-低调小熊猫
* @since 19-7-18
*/
public class CookXihongshi {
public void open(){
System.out.println("打开抽油烟机");
}
public void fire(){
System.out.println("生火");
}
public void doCook(){
System.out.println("西红柿炒蛋");
}
public void outfire(){
System.out.println("灭火");
}
public void close(){
System.out.println("关闭抽油烟机");
}
public void cook(){
this.open();
this.fire();
this.doCook();
this.outfire();
this.close();
}
}
/**
* 炒个青菜
* @author aodeng-低调小熊猫
* @since 19-7-18
*/
public class CookVegetable {
public void open(){
System.out.println("打开抽油烟机");
}
public void fire(){
System.out.println("生火");
}
public void doCook(){
System.out.println("炒青菜");
}
public void outfire(){
System.out.println("灭火");
}
public void close(){
System.out.println("关闭抽油烟机");
}
public void cook(){
this.open();
this.fire();
this.doCook();
this.outfire();
this.close();
}
}
炒青菜的类和上面西红柿炒蛋的类一比较,你会发现除了 doCook() 方法中具体的实现不一样之外,其他步骤都是完全一模一样的。解决办法很简单,将重复代码抽出来让父类去实现,而西红柿炒蛋和炒青菜都继承它,这样就避免了重复代码:
/**
* 抽象父类 两个地方是关键,一是 doCook() 使用 abstract 修饰,让子类去实现。二是 cook() 方法使用 final 关键字修饰,防止子类重写,从而破坏了模板中规定好的流程。
* @author aodeng-低调小熊猫
* @since 19-7-18
*/
public abstract class Cook {
public void open(){
System.out.println("打开抽油烟机");
}
public void fire(){
System.out.println("生火");
}
/**
* 期望子类去实现
*/
public abstract void doCook();
public void outfire(){
System.out.println("灭火");
}
public void close(){
System.out.println("关闭抽油烟机");
}
/**
* 使用final关键字,防止子类重写
*/
public final void cook(){
this.open();
this.fire();
this.doCook();
this.outfire();
this.close();
}
}
/**
* 子类重写 实现要炒的菜 西红柿炒蛋
* @author aodeng-低调小熊猫
* @since 19-7-18
*/
public class CookXihongshi2 extends Cook {
@Override
public void doCook() {
System.out.println("西红柿炒蛋");
}
}
/**
* 子类重写 实现要炒的菜 炒青菜
* @author aodeng-低调小熊猫
* @since 19-7-18
*/
public class CookVegetable2 extends Cook {
@Override
public void doCook() {
System.out.println("炒青菜");
}
}
System.out.println("Hello World!");
Cook cook = new CookXihongshi2();
cook.cook();
Cook cook1=new CookVegetable2();
cook1.cook();
/*
===== 控制台输出
Hello World!
打开抽油烟机
生火
西红柿炒蛋
灭火
关闭抽油烟机
打开抽油烟机
生火
炒青菜
灭火
关闭抽油烟机*/
看到这里,没错,你已经学会了模板方法模式。模板方法是设计模式中较好理解的一种,它的使用场景是:当有一个业务有 N 个步骤( 模板 ),其中一部分步骤是永恒不变的,那么就将不变的这些步骤抽象到父类中,可能变化的步骤留给子类去实现。