1 解决的问题

实现一个模板,只需要填充必要的组件。如,本人 ___ 因 ___ 需请假 ___ 天,望批准!,只需要填充姓名、原因、请假时间就可以了。

2 模板模式

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

通俗地说,模板方法模式就是一个关于继承的设计模式。

3 实现代码

abstract class LeaveRequest {
 
    void request() {
        System.out.print("本人");
        System.out.print(name());
        System.out.print("因");
        System.out.print(reason());
        System.out.print("需请假");
        System.out.print(duration());
        System.out.print("天,望批准");
    }
    abstract String name();
    abstract String reason();
    abstract String duration();
}
 
class MyLeaveRequest extends LeaveRequest {
    @Override    String name() { return "阿笠"; }
	@Override    String reason() { return "参加力扣周赛"; }
    @Override    String duration() { return "0.5"; }
}
// 输出:本人阿笠因参加力扣周赛需请假0.5天,望批准
new MyLeaveRequest().request();

4 更好地使用模板

  • 如果不希望子类覆写模板中的某个方法,使用 final 修饰此方法;
  • 如果要求子类必须覆写模板中的某个方法,使用 abstract 修饰此方法;
  • 如果没有特殊要求,可使用 protected 或 public 修饰此方法,子类可根据实际情况考虑是否覆写。

5 优缺点

优点

  • 去除子类中的重复代码,抽象模板保存通用代码逻辑,子类无需重复处理公用逻辑,只关注特定逻辑;
  • 子类对父类的反向控制,通过子类来决定父类算法中某个步骤是否执行;
  • 代码复用、封装、良好的扩展性;

缺点

  • 违反开闭原则,“对修改关闭”,子类执行结果受父类影响;
  • 增加代码阅读难度,子类多跳转也会很多,不方便联系上下文逻辑线索,模板中步骤越多,越难维护;
  • 违反里氏替换原则,替换子类,可能导致父类不可用或整体逻辑发生改变;

6 应用场景

  • 多个类具有相同方法且逻辑可共用时,将公共行为抽取并集中到公共父类中减少代码重复;
  • 通用算法、协议、固定流程设计为模板,在每个具体的子类中再继续优化算法步骤或流程步骤;