1. 介绍
1.1 定义
模版方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
1.2 模式中的方法
① 模版方法:
定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。
一个抽象类可以有任意多个模板方法,而不限于一个。每一个模板方法都可以调用任意多个具体方法。
注意: 子类不可以对模版方法进行覆盖或者重写。
② 基本方法:
- 抽象方法(Abstract Method):一个抽象方法由抽象类声明,由具体子类实现,是子类必须实现的方法。
- 钩子方法(Hook Method): 一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。它是子类可以选择性实现或不实现的方法。
- 具体方法(Concrete Method): 一个具体方法由抽象类声明并实现,而子类并不实现或置换。它是子类不可更改的方法。
2. Demo示例
2.1 类图
2.2 代码
package com.jbp.designpattern.template;
/**
* @ClassName: Game
* @description: 游戏基类
* @author: JiangBeiPing
* @create: 2021-07-30 17:30
* @Version: 1.0
**/
public abstract class Game {
// 初始化游戏
abstract void initialize();
// 开始游戏
abstract void startPlay();
// 结束游戏
abstract void endPlay();
// 钩子方法:让子类决定是否开始玩游戏
boolean isPlay(){
return true;
}
// 模板方法
public final void play(){
initialize();
// 如果子类决定玩,才会执行玩游戏的动作
if (this.isPlay()){
startPlay();
}
endPlay();
}
}
package com.jbp.designpattern.template;
/**
* @ClassName: Cricket
* @description: 板球游戏
* @author: JiangBeiPing
* @create: 2021-07-30 17:34
* @Version: 1.0
**/
public class Cricket extends Game{
@Override
void initialize() {
System.out.println("板球游戏:初始化游戏...");
}
@Override
void startPlay() {
System.out.println("板球游戏:开始游戏...");
}
@Override
void endPlay() {
System.out.println("板球游戏:结束游戏...");
}
}
package com.jbp.designpattern.template;
/**
* @ClassName: Football
* @description: 足球游戏
* @author: JiangBeiPing
* @create: 2021-08-02 11:02
* @Version: 1.0
**/
public class Football extends Game{
// 默认开始游戏
private boolean playFlag = true;
// 用户设置是否开始游戏
public void setPlayFlag(boolean flag){
playFlag = flag;
}
@Override
boolean isPlay() {
return this.playFlag;
}
@Override
void initialize() {
System.out.println("足球游戏:初始化游戏...");
}
@Override
void startPlay() {
System.out.println("足球游戏:开始游戏...");
}
@Override
void endPlay() {
System.out.println("足球游戏:结束游戏...");
}
}
测试:
package com.jbp.designpattern.template;
/**
* @ClassName: Test
* @description: 测试
* @author: JiangBeiPing
* @create: 2021-08-02 11:04
* @Version: 1.0
**/
public class Test {
public static void main(String[] args) {
Game cricket = new Cricket();
cricket.play();
System.out.println("========");
Game football = new Football();
football.play();
System.out.println("========");
Football football2 = new Football();
football2.setPlayFlag(false);
football2.play();
}
}
输出:
板球游戏:初始化游戏…
板球游戏:开始游戏…
板球游戏:结束游戏…
========
足球游戏:初始化游戏…
足球游戏:开始游戏…
足球游戏:结束游戏…
========
足球游戏:初始化游戏…
足球游戏:结束游戏…
3. 优缺点
优点:
- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类控制,子类实现
缺点:
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大