# 模板方法模式(Template Method Pattern)

目录: https://note.dolyw.com/design/ (opens new window)

代码地址

# 1. 介绍

模板方法模式中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式

模板方法模式定义了一个流程的骨架,由多个方法组成。并允许子类为一个或多个步骤提供实现。简而言之就是公共的不变的部分由父类统一实现,变化的部分由子类来个性化实现。

# 1.1. 特点

待补充

# 1.2. 结构

待补充

# 1.3. 优缺点

  • 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
  • 主要解决:一些方法通用,却在每一个子类都重新写了这一方法
  • 何时使用:有一些通用的方法
  • 如何解决:将这些通用算法抽象出来
  • 关键代码:在抽象类实现,其他步骤在子类实现
  • 使用场景:有多个子类共有的方法,且逻辑相同。重要的、复杂的方法,可以考虑作为模板方法
  • 优点:
    • 封装不变部分,扩展可变部分,符合开闭原则
    • 提高复用性,提取公共代码,便于维护
    • 行为由父类控制,子类实现
  • 缺点:
    • 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大
    • 父类添加新的抽象方法,所有子类都要改一遍(可以不写抽象,父类本身放一个空实现,这样子类就不用去强制实现)
  • 应用场景:
    • Spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来
    • 一个统一的流程,定义好步骤,子类去扩展可变部分
  • 注意事项:为防止恶意操作,一般模板方法都加上 final 关键词

# 2. 代码

比如一个小游戏的模板方法

/**
 * 模板方法 - 创建一个抽象类,它的模板方法被设置为 final
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:00
 */
public abstract class Game {

    /**
     * 初始化
     */
    abstract void initialize();

    /**
     * 开始游戏
     */
    abstract void startPlay();

    /**
     * 结束游戏
     */
    abstract void endPlay();

    /**
     * 模板
     */
    public final void play() {
        // 初始化游戏
        initialize();

        // 开始游戏
        startPlay();

        // 结束游戏
        endPlay();
    }
}
/**
 * 坦克大战的实现
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:00
 */
public class TankGameImpl extends Game {
    @Override
    void initialize() {
        System.out.println("坦克大战初始化");
    }

    @Override
    void startPlay() {
        System.out.println("坦克大战开始游戏");
    }

    @Override
    void endPlay() {
        System.out.println("坦克大战结束游戏");
    }
}
/**
 * 贪吃蛇的实现
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:00
 */
public class SnakeGameImpl extends Game {
    @Override
    void initialize() {
        System.out.println("贪吃蛇初始化");
    }

    @Override
    void startPlay() {
        System.out.println("贪吃蛇开始游戏");
    }

    @Override
    void endPlay() {
        System.out.println("贪吃蛇结束游戏");
    }
}
/**
 * 模板方法
 *
 * @author wliduo[i@dolyw.com]
 * @date 2023/2/2 10:02
 */
public class Main {

    public static void main(String[] args) {
        // 使用 Game 的模板方法 play() 来演示游戏的定义方式
        Game tankGame = new TankGameImpl();
        tankGame.play();
        System.out.println("------------");
        Game snakeGame = new SnakeGameImpl();
        snakeGame.play();
    }
}
坦克大战初始化
坦克大战开始游戏
坦克大战结束游戏
------------
贪吃蛇初始化
贪吃蛇开始游戏
贪吃蛇结束游戏
上次更新时间: 2023-12-15 03:14:55