行为型模式(一) 模板方法模式(Template Method)
一、动机(Motivate)
“模板方法”,就是有一个方法包含了一个模板,这个模板是一个算法。在我们的现实生活中有很多例子可以拿来说明这个模式,就拿吃饺子这个事情来说,要想吃到饺子必须经过三步,第一步是“和面”,第二步是“包馅”,第三步是“煮饺子”,这三步就是一个算法,我们要想吃到不同的面和馅的饺子,对这三步中的任意一步就行操作就可以,也可以完全定义这三步
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?
二、意图(Intent)
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 ——《设计模式》GoF
三、结构图

四、模式的组成
模板方法模式参与者:
(1)、抽象类角色(AbstractClass):定义一个模板方法(TemplateMethod),在该方法中包含着一个算法的骨架,具体的算法步骤是PrimitiveOperation1方法和PrimitiveOperation2方法,该抽象类的子类将重定义PrimitiveOperation1和PrimitiveOperation2操作。
(2)、具体类角色(ConcreteClass):实现PrimitiveOperation1方法和PrimitiveOperation2方法以完成算法中与特定子类(Client)相关的内容。
在模板方法模式中,AbstractClass中的TemplateMethod提供了一个标准模板,该模板包含PrimitiveOperation1和PrimitiveOperation2两个方法,这两个方法的内容Client可以根据自己的需要重写。
五、模板方法模式的具体实现
下面以生活中吃饺子为例来实现模板方法模式。在现实生活中,做饺子的步骤都大致相同,如果我们针对每种饺子的做法都定义一个类,这样在每个类中都有很多相同的代码,为了解决这个问题,我们一般的思路肯定是把相同的部分抽象出来到抽象类中去定义,具体子类来实现具体的不同部分,这个思路也正式模板方法的实现精髓所在,具体实现代码如下:
static void Main(string[] args)
{
//现在想吃绿色面的,猪肉大葱馅的饺子
AbstractClass fan = new ConcreteClass1();
fan.EatDumplings(); Console.WriteLine();
//过了段时间,我开始想吃橙色面的,韭菜鸡蛋馅的饺子
fan = new ConcreteClass2();
fan.EatDumplings();
} //该类型就是抽象类角色--AbstractClass,定义做饺子的算法骨架,这里有三步骤,当然也可以有多个步骤,根据实际需要而定
public abstract class AbstractClass
{
//该方法就是模板方法,方法里面包含了做饺子的算法步骤,模板方法可以返回结果,也可以是void类型,视具体情况而定
public void EatDumplings()
{
MakingDough();//和面
MakeDumplings();//包馅
BoiledDumplings(); //煮饺子
Console.WriteLine("饺子真好吃!");
} public abstract void MakingDough();//要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
public abstract void MakeDumplings();//要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
public abstract void BoiledDumplings(); //要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
} //该类型是具体类角色--ConcreteClass,我想吃绿色面皮,猪肉大葱馅的饺子
public sealed class ConcreteClass1 : AbstractClass
{
public override void MakingDough() //要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
{
Console.WriteLine("在和面的时候加入芹菜汁,和好的面就是绿色的");//我想要面是绿色的,绿色健康嘛,就可以在此步定制了
} public override void MakeDumplings()//要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
{
Console.WriteLine("农家猪肉和农家大葱,制作成馅");//我想吃猪肉大葱馅的,在此步就可以定制了
} public override void BoiledDumplings()//要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
{
Console.WriteLine("用我家的大铁锅和大木材煮饺子");//我想吃大铁锅煮的饺子,有家的味道,在此步就可以定制了
}
} //该类型是具体类角色--ConcreteClass2,我想吃橙色面皮,韭菜鸡蛋馅的饺子
public sealed class ConcreteClass2 : AbstractClass
{
public override void MakingDough()//要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
{
Console.WriteLine("在和面的时候加入胡萝卜汁,和好的面就是橙色的");//我想要面是橙色的,加入胡萝卜汁就可以。在此步定制就可以了。
} public override void MakeDumplings() //要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
{
Console.WriteLine("农家鸡蛋和农家韭菜,制作成馅"); //我想吃韭菜鸡蛋馅的,在此步就可以定制了
} public override void BoiledDumplings()//要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
{
Console.WriteLine("可以用一般煤气和不粘锅煮就可以"); //此处没要求
}
}
六、模板方法模式的实现要点:
Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展,是代码复用方面的基本实现结构。除了可以灵活应对子步骤的变化外,“Don't call me, let me call you(不要调用我,让我来调用你)”的反向控制结构是Template Method的典型应用。
1、模板方法模式适用情形:
(1)、 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
(2)、 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
(3)、 控制子类扩展。模板方法只允许在特定点进行扩展,而模板部分则是稳定的。
2、模板方法模式特点:
(1)、 TemplateMethod模式是一种非常基础性的设计模式,在面向对象系统中大量应用。它用最简洁的机制(基础、多态)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
(2)、 在具体实现方面,被TemplateMethod调用的虚方法可以具有实现,也可以没有任何实现(抽象方法或虚方法)。但一般推荐将它们设置为protected方法使得只有子类可以访问它们。
(3)、 模板方法模式通过对子类的扩展增加新的行为,符合“开闭原则”。
七、.NET 中模板模式的实现
这种模式在控件设计中大量的用到,比如:控件有自己的生命周期,Page对象也有自己的生命周期,Application应用对象也有自己的生命周期,这个生命周期里面的每个阶段其实就是模板方法里面包含的每个步骤,这些阶段步骤会被一个方法包含着,这个方法就是“模板方法”。让我们再说说控件吧,因为写好的控件,可能需要被开发人员自定义,那么在控件里我们已经定义好了控件呈现、动作的骨架,但是有些自定义的需求,需要延迟到扩展控件的开发人员来决定。
当我们在做Windows应用程序的时候,就会使用Windows控件,那Windows控件是如何显示在Windows Form 上的呢,就需要一个OnPaint方法把控件画出来,这里OnPaint是一个虚方法的子步骤,这就是一个Template Method设计模式。如果我们不去重写这个OnPaint方法,它就有一个基本的默认实现,画一个空窗体。这里我们并没有调用OnPaint方法,而是Application的Run会进入Windows的消息循环结构,Paint就是一个消息。当我们移动一下窗口都会导致Paint事件的发生,并导致OnPaint函数的调用,这就是一种反向调用。当然,还有很多其他的子步骤可以提供扩展点,例如OnClose等,很多以On开头的全部都是Template Method模式的虚方法。 这个里面内容很复杂,它并不是用一个Template Method在里面调用所有的子步骤方法,它实际上是把整体的Template Method方法置于了一个消息循环的结构里面,我们可以把消息循环的结构看做模板方法里面的TemplateMethod公有非虚方法。
行为型模式(一) 模板方法模式(Template Method)的更多相关文章
- 设计模式的征途—17.模板方法(Template Method)模式
在现实生活中,很多事情都需要经过几个步骤才能完成,例如请客吃饭,无论吃什么,一般都包含:点单.吃东西.买单等几个步骤,通常情况下这几个步骤的次序是:点单=>吃东西=>买单.在这3个步骤中, ...
- Android设计模式之命令模式、策略模式、模板方法模式
命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从 ...
- 简介Python设计模式中的代理模式与模板方法模式编程
简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...
- 设计模式17---设计模式之模板方法模式(Template Method)(行为型)
1.场景模拟 使用软件模拟登录控制,普通用户和工作人员用户,工作人员的密码在数据库中是加密的. 步骤大致如下: 前台提交,后台获取登录信息,同数据库中的登陆信息进行比较,只不过工作人员是加密的,普通用 ...
- 【java设计模式】之 模板方法(Template Method)模式
1. 模板方法的一个实例 这一节主要来学习一下设计模式中的模板方法模式.我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验 ...
- 编程模式之模板方法模式(Template Method)
模板方法模式由两个角色组成:父类角色,子类角色. 父类角色:提供模板. 子类角色:为父类模板提供实现. 类图: JAVA代码: AbstractClass.java package com.templ ...
- 行为类模式(十):模板方法(Template Method)
定义 定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. UML 优点 模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复 ...
- 模板方法(Template Method)模式
/* * 抽象模版(AbstractClass)角色有如下的责任: 定义了一个或多个抽象操作,以便让子类实现.这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤. 定义并实现了一个模版方法.这个模 ...
- 设计模式---组件协作模式之模板方法模式(Tempalte Method)
前提:组件协作模式 现代软件专业分工之后的第一个结构是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常见的模式. 我们常常使用框架来写自己的 ...
随机推荐
- saltstack配置文件详解
软件依赖 Python版本大于2.6或版本小于3.0: 对Python版本要求 msgpack-python: SalStack消息交换库 YAML: SaltStack配置解析定义语法 Jinja2 ...
- 第5/7Beta冲刺
1.团队成员 成员姓名 成员学号 秦裕航 201731062432(组长) 刘东 201731062227 张旭 201731062129 王伟 201731062214 2.SCRU部分 2.1各成 ...
- XML解析详解|乐字节
大家好,乐字节的小乐又来了,Java技术分享哪里少的了小乐!上次我们说了可扩展标记语言XML之二:XML语言格式规范.文档组成,本文将介绍重点——XML解析. 基本的解析方式有两种:一种叫 SAX ...
- mysql 逻辑运算符
NOT! 逻辑非. 如果操作数为 0,返回 1:如果操作数为非零,返回 0:如果操作数为 NOT NULL,返回 NULL. mysql> SELECT NOT 10; -> 0 mysq ...
- TCP/IP学习笔记4--网络地址
"他强由他强,清风拂山岗.他横由他横,明月照大江.世间诸事,敞开心扉,顺其自然." -- 张大千 地址具有两个特性: 1:唯一性 同一个通信网络中的任意两个通信主体不能具有相同的地 ...
- react-native-typescript-项目环境搭建
1.yarn global add create-react-native-app //全局安装 2.create-react-native-app 项目名称 3.yarn add typescrip ...
- beego 读取配置
不知道是不是坑 官方文档 https://beego.me/docs/module/config.md . 解决办法: 1 导入 config "github.com/astaxie/bee ...
- LOJ3120 CTS2019 珍珠 生成函数、二项式反演、NTT
传送门 题目大意:给出一个长度为\(n\)的序列\(a_i\),序列中每一个数可以取\(1\)到\(D\)中的所有数.问共有多少个序列满足:设\(p_i\)表示第\(i\)个数在序列中出现的次数,\( ...
- mybatis 多个中间表查询映射
最近项目用到中间表,则遇到如何联查映射的问题,之前一直都是一个表头,多个明细或者一对一这样的关系,没遇到这样的问题,所以趁机找了下资料解决了这个问题. 表结构设计如下: 主表: CREATE TABL ...
- php ajax生成excel并下载
目标:使用php,通过ajax请求的方式生成一个excel,然后下载. 思路:大致思路是发送一个ajax请求到后台,后台php处理后生成一个excel文件,然后把生成的文件放到一个临时目录,然后把文件 ...