一、介绍
1.1 定义
定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
1.2 解决的问题
(1)提高代码复用性,将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中
(2)实现了反向控制 ,通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 & 符合“开闭原则”
二、实例讲解
2.1 案例描述
以我们现实生活中的旅游为例
上海旅游:1.查阅旅游攻略 2.制定出行计划 3.准备食物 4.收拾行李 5.乘汽车出行 6.游览东方明珠 7.返程回家
北京旅游:1.查阅旅游攻略 2.制定出行计划 3.准备食物 4.收拾行李 5.乘动车出行 6.游览故宫 7.返程回家
观察上述两种旅游计划,相信小伙伴已经发下其中端倪,除了步骤5跟步骤6不同,其余步骤都是完全相同的,这就可以使用模板方法模式,定义旅游的框架,将步骤5跟步骤6延迟到具体子类中实现
2.2 代码实现
2.2.1 创建抽象模板结构(Abstract Class)
package com.templateMethod;
public abstract class AbstractTravel {
//申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序
public final void travelProcess() {
//第一步:查询旅游攻略
this.searchVipgonglue();
//第二步:制定出行计划
this.makeTravelPlan();
//第三步:准备食物
this.prepareFood();
//第四步:收拾行李
this.packUp();
//第五步:出行方式
this.tripMode();
//第六步:旅游景点
this.touristAttractions();
//第七步:返程回家
this.goHome();
}
/**
* 查询旅游攻略
*/
protected void searchVipgonglue(){
System.out.println("查询旅游攻略");
}
/**
* 制定出行计划
*/
protected void makeTravelPlan(){
System.out.println("制定出行计划");
}
/**
* 准备食物
*/
protected void prepareFood(){
System.out.println("准备食物");
}
/**
* 收拾行李
*/
protected void packUp(){
System.out.println("收拾行李");
}
/**
* 出行方式
*/
protected abstract void tripMode();
/**
* 旅游景点
*/
protected abstract void touristAttractions();
/**
* 返程回家
*/
protected void goHome(){
System.out.println("玩好了就回家吧");
}
}
2.2.2 创建具体模板(ShangHaiTravel Class),即上海旅游
package com.templateMethod;
/**
* 上海旅游
*/
public class ShangHaiTravel extends AbstractTravel {
@Override
protected void tripMode() {
System.out.println("乘飞机出行");
}
@Override
protected void touristAttractions() {
System.out.println("游览东方明珠");
}
}
2.2.3 创建具体模板(BeiJingTravel Class),即北京旅游
package com.templateMethod;
/**
* 北京旅游
*/
public class BeiJingTravel extends AbstractTravel {
@Override
protected void tripMode() {
System.out.println("乘动车出行");
}
@Override
protected void touristAttractions() {
System.out.println("游览故宫");
}
}
2.2.4 测试代码
package com.templateMethod;
public class TravelTest {
public static void main(String[] args){
BeiJingTravel bj = new BeiJingTravel();
bj.travelProcess();
System.out.println("-------------------------------------------");
ShangHaiTravel sh = new ShangHaiTravel();
sh.travelProcess();
}
}
2.2.5 测试结果
三、应用场景
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现;
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复;
- 控制子类的扩展。