设计模式——模板模式
简介
在面向对象程序设计中,程序员常常面临这样的情况:需要设计一个系统,已经明确了算法的关键步骤和它们的执行顺序,但某些步骤的具体实现尚未确定,或者某些步骤的实现方式取决于特定的环境或需求。一个常见的例子是医院看病流程,其中包括挂号、排队、就诊、取药等步骤。挂号和排队这两个步骤对每个病人都是相同的,可以在一个通用的父类中实现。但是,就诊和取药的具体细节因个体差异而异,需要留给子类来实现。这种情况下,我们可以创建一个模板,定义了通用的流程或格式,允许系统的使用者根据自身需求来扩展或修改这个模板,以满足特定的场景或需求。这就是模板模式的核心思想,它提供了一种框架,允许定制化实现算法的部分,而不改变整体算法的结构。这样可以提高代码的重用性和灵活性。
特点
- 封装了不变的部分,扩展可变部分。将不变部分的算法封装到父类中实现,而把可变部分的算法由各子类实现。便于子类继续扩展。
- 在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
应用场景
- 当多个子类具有公用的方法,却执行流程逻辑相同时。
- 重要的、复杂的方法,可以考虑作为模板方法。
注:为了防止恶意操作,一般模板方法上都加有 final 关键字。
工作原理
模板模式通常包括以下几个关键组成部分:
-
抽象模板(Abstract Template):定义算法的骨架,包括一组抽象步骤或操作,这些步骤可以是抽象的,由具体子类来实现。
-
具体模板(Concrete Template):实现抽象模板中定义的抽象步骤,这些步骤的具体实现可以在具体模板中提供。
-
钩子方法(Hook Method):在抽象模板中可以包含一些钩子方法,这些方法是可选的,具体子类可以选择性地实现它们(子类根据情况要不要重写此方法),以影响算法的行为。
模板模式的工作原理如下:
-
定义一个抽象模板,其中包含算法的骨架,其中包括多个步骤,这些步骤可能是抽象的。
-
具体子类继承抽象模板,并实现具体的步骤,将抽象步骤具体化。
-
抽象模板中的步骤可以包含钩子方法,具体子类可以选择性地实现这些方法。
-
客户端代码使用具体子类来执行算法,而无需了解算法的具体实现细节。
应用示例
// 抽象模板
abstract class AbstractAlgorithm {
public void execute() {
step1();
step2();
step3();
}
abstract void step1();
abstract void step2();
void step3() {
// 默认实现,可被子类覆盖
System.out.println("Default implementation of step 3");
}
}
// 具体模板
class ConcreteAlgorithm extends AbstractAlgorithm {
@Override
void step1() {
System.out.println("Step 1");
}
@Override
void step2() {
System.out.println("Step 2");
}
@Override
void step3() {
System.out.println("Custom implementation of step 3");
}
}
public class TemplatePatternExample {
public static void main(String[] args) {
AbstractAlgorithm algorithm = new ConcreteAlgorithm();
algorithm.execute();
}
}