行为型 简单
模板方法模式
Template Method Pattern
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
概述
模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。
适用场景
- •当你只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时
- •当你有几个类包含相似的、仅在特定步骤上有所不同的算法时
- •当你需要控制子类扩展的方式,只允许在特定点进行扩展时
- •当你希望避免代码重复,将通用行为提取到父类中时
优点
- +你可以仅允许客户端重写一个大型算法中的特定部分,使得修改其他部分所造成的影响减小
- +你可以将重复代码提取到一个超类中
- +模板方法提供了一种反向控制结构,允许父类调用子类的方法(好莱坞原则:"别调用我们,我们会调用你")
- +通过钩子方法,子类可以选择性地扩展算法的某些步骤
缺点
- −部分客户端可能会受到算法框架的限制
- −通过子类来抑制默认步骤实现可能会导致违反里氏替换原则
- −模板方法中的步骤越多,其维护工作就可能会越困难
- −继承的固有限制:一旦算法发生变化,可能需要修改所有子类
结构
classDiagram
class AbstractClass {
+templateMethod()
+baseOperation1()
+baseOperation2()
+abstract requiredOperation1()
+abstract requiredOperation2()
+hook()
}
class ConcreteClass1 {
+requiredOperation1()
+requiredOperation2()
}
class ConcreteClass2 {
+requiredOperation1()
+requiredOperation2()
+hook()
}
class Client {
+main()
}
AbstractClass <|-- ConcreteClass1
AbstractClass <|-- ConcreteClass2
Client ..> AbstractClass : uses
style AbstractClass fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style ConcreteClass1 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
style ConcreteClass2 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
style Client fill:#f5f5f5,stroke:#616161,stroke-width:1px
交互演示
定义算法骨架,子类实现步骤
选择算法
算法步骤
○ openFile()
○ parseFile()
○ analyze()
○ sendReport()
选择算法,观察模板方法如何定义骨架,具体步骤由子类实现
生活类比
模板方法就像是建筑蓝图或食谱,定义了固定的步骤顺序,但某些细节可以灵活调整
建筑蓝图
建筑师提供建筑蓝图(模板),定义了建造的步骤顺序:地基 → 框架 → 墙体 → 屋顶。但具体材料选择(混凝土还是钢结构)可以由施工方决定。
食谱烹饪
食谱规定了烹饪的步骤顺序:准备食材 → 加热 → 调味 → 装盘。但具体的调味方式(辣度、咸度)可以根据个人口味调整。
面试流程
公司面试有固定流程:简历筛选 → 笔试 → 技术面试 → HR面试。但每个环节的具体问题可以根据候选人背景灵活调整。
代码实现
Example.java
实际应用
Java Servlet
Java Servlet 的 doGet、doPost 方法是模板方法模式的典型应用。service() 方法作为模板方法定义了请求处理流程,doGet/doPost 等作为钩子方法供子类实现。
Example.java
Spring Framework - JdbcTemplate
Spring 的 JdbcTemplate 使用模板方法模式封装 JDBC 操作流程,用户只需实现特定的回调接口来定制查询或更新逻辑。
Example.java
JUnit 测试框架
JUnit 的 TestCase 类使用模板方法模式,setUp() 和 tearDown() 作为钩子方法,runTest() 作为模板方法定义测试执行流程。
Example.java
练习
1
模板方法模式的主要目的是什么?
2
模板方法应该被声明为 final 以防止子类重写
3
钩子方法(Hook Method)的主要作用是什么?
4