模式概述

在现实生活中,很多事情都包含几个实现步骤,例如请客吃饭,无论吃什么,一般都包含点单、吃东西、买单等几个步骤,通常情况下这几个步骤的次序是:点单 --> 吃东西 --> 买单。

在这三个步骤中,点单和买单大同小异,最大的区别在于第二步——吃什么?不同的人、不同的地方有不同的饮食习惯。如果站在软件工程的角度来看,这就是变化的地方,也可以说是可扩展的点。

软件开发中,经常会遇到类似的情况,某个方法的实现需要多个步骤(类似“请客”),其中有些步骤是固定的(类似“点单”和“买单”),而有些步骤并不固定,存在可变性(类似“吃东西”)。

为了提高代码的复用性和系统的灵活性,可以使用一种称之为模板方法模式的设计模式来对这类情况进行设计。

在模板方法模式中,将实现功能的每一个步骤所对应的方法称为基本方法(例如“点单”、“吃东西”和“买单”),而调用这些基本方法同时定义基本方法的执行次序的方法称为模板方法(例如“请客”)。

在模板方法模式中,可以将相同的代码放在父类中,例如将模板方法“请客”以及基本方法“点单”和“买单”的实现放在父类中,而对于基本方法“吃东西”,在父类中只做一个声明,将其具体实现放在不同的子类中,在一个子类中提供“吃面条”的实现,而另一个子类提供“吃米饭”的实现。

通过使用模板方法模式,一方面提高了代码的复用性,另一方面还可以利用面向对象的多态性,在运行时选择一种具体子类,实现完整的“请客”方法,提高系统的灵活性和可扩展性。

模式定义

模板方法模式定义如下:

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

模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。

模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

模式结构图

模板方法模式结构比较简单,其核心是抽象类和其中的模板方法的设计,其结构如下图所示:

模板方法模式包含如下两个角色:

  • AbstractClass(抽象类):在抽象类中定义了一系列基本操作(Primitive Operations),这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
  • ConcreteClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

模式伪代码

抽象父类AbstractClass负责给出一个算法的轮廓和框架,如下:

/**
* 抽象模板
*/
public abstract class AbstractClass { /**
* 具体方法1
*/
public void method1() { } /**
* 抽象方法2
*/
public abstract void method2(); /**
* 具体方法3
*/
public void method3() { } /**
* 模板方法
*/
public void templateMethod() {
method1();
method2();
method3();
}
}

其中实现这些具体逻辑步骤的方法即为基本方法,而将这些基本方法汇总起来的方法即为模板方法。

子类ConcreteClass负责给出这个算法的各个逻辑实现,如下:

public class ConcreteClass extends AbstractClass {

    @Override
public void method2() {
// 抽象步骤的实现
} @Override
public void method3() {
// 也可覆盖父类中已经实现的具体方法
super.method3();
}
}

这样,就可以通过扩展不同的子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。

模式总结

写代码的一个很重要的思考点就是变与不变,程序中哪些功能是可变的,哪些功能是不变的,我们可以把不变的部分提取出来,进行公共的实现,把变化的部分分离出来,用接口来封装隔离变化,或用抽象类约束子类行为。模板方法模式就很好的体现了这一点。

模板方法模式是基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用较为频繁的模式。模板方法模式广泛应用于框架设计中,以确保通过父类来控制处理流程的逻辑顺序(如框架的初始化,测试流程的设置等)。

主要优点

  • 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序
  • 模板方法模式是一种代码复用技术,它提取了公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用
  • 可实现一种反向控制结构,通过子类覆盖父类的方法来决定某一特定步骤是否需要执行
  • 通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则

主要缺点

需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合 桥接模式 来进行设计。

适用场景

  • 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中
  • 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制

参考书籍:

《设计模式的艺术之道(软件开发人员内功修炼之道)》—— 刘伟

模板方法模式(Template Method Pattern)——复杂流程步骤的设计的更多相关文章

  1. 乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern)

    原文:乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 模板方法模式(Template Method ...

  2. 设计模式 - 模板方法模式(template method pattern) 具体解释

    模板方法模式(template method pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 模板方法模式(template metho ...

  3. 二十四种设计模式:模板方法模式(Template Method Pattern)

    模板方法模式(Template Method Pattern) 介绍定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method使得子类可以不改变一个算法的结构即可重定义该算法 ...

  4. 设计模式 - 模板方法模式(template method pattern) JFrame 具体解释

    模板方法模式(template method pattern) JFrame 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考模板方法模式(templ ...

  5. 设计模式 - 模板方法模式(template method pattern) 排序(sort) 具体解释

    模板方法模式(template method pattern) 排序(sort) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考模板方法模式(tem ...

  6. 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)

    今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...

  7. 模板方法模式(Template Method Pattern)

    模板方法模式是一种基于继承的代码复用技术,定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 模式中的角色 抽象类(Abstrac ...

  8. 使用 C# (.NET Core) 实现模板方法模式 (Template Method Pattern)

    本文的概念内容来自深入浅出设计模式一书. 项目需求 有一家咖啡店, 供应咖啡和茶, 它们的工序如下: 咖啡: 茶: 可以看到咖啡和茶的制作工序是差不多的, 都是有4步, 其中有两步它们两个是一样的, ...

  9. 使用C# (.NET Core) 实现模板方法模式 (Template Method Pattern)

    本文的概念内容来自深入浅出设计模式一书. 项目需求 有一家咖啡店, 供应咖啡和茶, 它们的工序如下: 咖啡: 茶: 可以看到咖啡和茶的制作工序是差不多的, 都是有4步, 其中有两步它们两个是一样的, ...

随机推荐

  1. 大爽Python入门教程 2-3 字符串,列表,字典

    大爽Python入门公开课教案 点击查看教程总目录 除了通用的序列方法, 列表和字符串还有些自己的专属方法. 后面介绍有些是英中文对照介绍(英文来自官方文档), 便于大家更深入的去理解其意思. 灵活的 ...

  2. linux auditd审计的简单使用和理解

    Linux审计主要用于查看系统改动的信息,如系统密码修改,用户的新建,主要用于保障系统的安全,下面简单介绍审计如何使用 1启动审计进程: [tommy@xie-testlog]$ sudo servi ...

  3. 最大连续子数组和--dp

    最大连续子数组和 问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的子段和的最大值.当所给的整数均为负数时定义子段 ...

  4. [luogu5537]系统设计

    考虑哈希,令$h[x]$表示根到$x$路径的哈希值,那么有$h[x]+hash(l,r)=h[ans]$ 考虑用线段树维护$a_{i}$的区间哈希值,并用map去找到对应的$ans$ 但还有一个问题, ...

  5. java实现自动化发布平台核心代码

    1.搭建jenkins环境 (1)jenkins官网下载jenkins.war包 (2)将该war包放入到tomcat的webapp的目录下(前提条件需要配置tomcat的环境,详情请自行百度) (3 ...

  6. 『学了就忘』Linux文件系统管理 — 58、常用硬盘管理相关命令

    目录 1.df命令 2.du命令 3.fsck文件系统修复命令 4.显示磁盘状态dumpe2fs 5.查看文件的详细时间 6.判断文件类型 1.df命令 df命令用于统计分区的占用状况. [root@ ...

  7. Codeforces 1290D - Coffee Varieties(分块暴力+完全图的链覆盖)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 发现自己交互题烂得跟 s ...

  8. 【机器学*与R语言】2-懒惰学*K*邻(kNN)

    目录 1.理解使用KNN进行分类 KNN特点 KNN步骤 1)计算距离 2)选择合适的K 3)数据准备 2.用KNN诊断乳腺癌 1)收集数据 2)探索和准备数据 3)训练模型 4)评估模型的性能 5) ...

  9. PAML 选择压力的计算

    简介 PAML(Phylogenetic Analysis by Maximum Likelihood)是伦敦大学的杨子恒(Yang Ziheng)教 授开发的一套基于最大似然估计来对蛋白质和核酸序列 ...

  10. 58-Odd Even Linked List

    Odd Even Linked List My Submissions QuestionEditorial Solution Total Accepted: 29496 Total Submissio ...