定义
这种类型的设计模式属于行为型模式。它定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤。换句话说,模板模式会定义了算法的固定执行逻辑,这个执行逻辑是有父类来控制的,同时将公用的方法逻辑放到父类中维护,而可能改变的方法延迟到子类中实现。
优缺点
优点:
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
缺点:
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
应用场景
1.多个子类有相同的逻辑
2.将公共的行为抽取出来放到一个公共类中,子类通过继承公共类来获取公共方法的使用
3.多个子类中差异性的内容放到子类里实现
角色
抽象方法:在抽象类声明、由其具体子类实现。
具体方法:在抽象类中声明并实现,在具体子类中可以继承或重写。
钩子方法:在抽象类中声明并实现(可以是空的实现),子类视情况进行重写覆盖,一般是逻辑判断方法。
模板方法:定义统一模板算法的方法,提供实现方法,子类一般不需要重写。
模板模式和策略模式的区别
模板模式定义了一个统一的算法,子类可以对算法的某一些步骤,进行覆盖重写,可以提高代码的复用率。同过继承的方式实现,依赖比较强,不够灵活。
策略模式每个子类都是一种实现,可以完全不相同,即便算法之间存在共性,也需要在每个子类重新实现,通过组合的方式实现,可以动态的改变算法,比较灵活。
代码
抽象类
public abstract class Game { /** * 具体方法 */ public void initialize() { System.out.println("game initialize ........."); } /** * 抽象方法 */ abstract void startPlay(); abstract void endPlay(); /** * 钩子方法 * * @return 是否需要结束 */ boolean isNeedEnd() { return false; } /** * 模板方法 * final修饰 不允许子类修改 * 每一个游戏先初始化、开始游戏 是否需要结束游戏 根据钩子进行判断 */ public final void play() { //初始化游戏 initialize(); //开始游戏 startPlay(); if (isNeedEnd()) { //结束游戏 endPlay(); } } }
具体类
/** * 具体模板 * 足球游戏 */ public class Football extends Game{ @Override void endPlay() { System.out.println("Football Game Finished!"); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } @Override boolean isNeedEnd() { return false; } }
测试类
/** * 模板测试类 */ public class TemplateModeTest { public static void main(String[] args) { Game game = new Basketball(); game.play(); game = new Football(); game.play(); } }