C#设计模式之9:模板方法
模板方法
模板方法是一个方法,定义了算法的步骤,并允许子类为一个或多个步骤提供实现。
本例中用冲泡咖啡和茶的例子来说明:

上图说明了冲泡咖啡和茶的步骤,可以看出冲泡咖啡和茶的步骤差不多,很相似,先来看看没有应用模板方法的代码:

Tea的代码类似,就不放了。他们的一个不好的地方在于算法散落在了各个类中,还有一点是重复的代码。
public abstract class CaffeineBeverage//设计一个抽象类,将算法进行封装
{
public void BoilWater()
{
Console.WriteLine("boil water");
} public void PourInCup()
{
Console.WriteLine("pour in cup");
} public void PrepareRecipe()//封装算法,这个就是模板方法。
{
BoilWater();
Brew();
PourInCup();
AddCondiment();
}
public abstract void Brew();//具体的实现要到子类中实现
public abstract void AddCondiment();//具体的实现要到子类中实现
}
public class TeaLogic: CaffeineBeverage
{
public override void Brew()
{
Console.WriteLine("brew tea");
} public override void AddCondiment()
{
Console.WriteLine("add some lemon");
}
}
public class CoffeLogin:CaffeineBeverage
{
public override void Brew()
{
Console.WriteLine("brew coffe...");
} public override void AddCondiment()
{
Console.WriteLine("add some milk and sugar...");
}
}
模板方法定义了一个算法步骤,并允许子类其中一个或多个实现提供步骤。
模板方法的定义:在一个方法中定义算法的骨架,而将一些步骤延迟到子类中。模板方法可以在子类不改变算法结构的情况下,重新定义算法中的某些步骤。

同时,AbstractClass内部定义一个钩子方法——一个虚方法,可以在子类中决定是否重写,达到挂钩的目的。钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,由子类自行决定。
//在模板方法中应用钩子
public abstract class AnotherKindOfCoffeineBeverage
{
public void BoilWater()
{
Console.WriteLine("boil water");
}
public void PourInCup()
{
Console.WriteLine("pour in cup..");
}
public virtual bool CustomerWantCondiment()//虚方法。。表示一个钩子
{
return true;
}
public abstract void Brew();
public abstract void AddCondiment();
public void PrepareRecipe()
{
BoilWater();
Brew();
if (CustomerWantCondiment())
{
AddCondiment();
}
PourInCup();
}
}
//应用钩子方法的一个场景
public class AnotherKindOfTea : AnotherKindOfCoffeineBeverage
{
public override bool CustomerWantCondiment()
{
return GetCustomerInput().Equals("y");
}
public override void Brew()
{
Console.WriteLine("dropping coffe through filter..");
}
public override void AddCondiment()
{
Console.WriteLine("add some condiment..");
}
private string GetCustomerInput()
{
Console.WriteLine("would you like some lemon with your tea?(y/n)");
var input = Console.ReadLine();
return input?.ToLower();
}
}
关于钩子,由这么一个原则:当你必须提供模板方法中的某个步骤时,就在基类中做成抽象方法,如果这个步骤是可选的,就做成虚方法,钩子。
钩子可以让子类实现算法中的可选部分,或者在钩子对于子类的实现不那么重要的时候,子类可以对此钩子置之不理。钩子的另一个用法,是让子类能够有机会对模板方法中某些即将发生的步骤做出反应。钩子也可以让子类有能力为其抽象类做一些决定。
最重要的一点:抽象类中的某些方法是可选的,对于这些可选的方法,就做成钩子,而不是做成抽象方法,这样就可以让子类的负荷减轻。
新的设计原则:好莱坞设计原则——不要调用(打电话给)我们,我会调用(打电话给)你。


好莱坞原则和模板方法
他们两个的联系还算是比较明显:当我们设计模板方法时,我们告诉子类,“不要调用我们,我们会调用你”。

好莱坞原则和依赖倒置原则之间的关系:

C#设计模式之9:模板方法的更多相关文章
- 设计模式 ( 十九 ) 模板方法模式Template method(类行为型)
设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行 ...
- 【java设计模式】之 模板方法(Template Method)模式
1. 模板方法的一个实例 这一节主要来学习一下设计模式中的模板方法模式.我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验 ...
- c#设计模式系列:模板方法模式(Template Method Pattern)
引言 提到模板,大家肯定不免想到生活中的"简历模板"."论文模板"."Word中模版文件"等,在现实生活中,模板的概念就是--有一个规定的格 ...
- C#设计模式系列:模板方法模式(Template Method)
你去银行取款的时候,银行会给你一张取款单,这张取款单就是一个模板,它把公共的内容提取到模板中,只留下部分让用户来填写.在软件系统中,将多个类的共有内容提取到一个模板中的思想便是模板方法模式的思想. 模 ...
- javascript设计模式实践之模板方法--具有百叶窗切换图片效果的JQuery插件(二)
在上一篇<javascript设计模式实践之迭代器--具有百叶窗切换图片效果的JQuery插件(一)>里,通过采用迭代器模式完成了各初始化函数的定义和调用. 接下来就要完成各个切换效果的编 ...
- Java设计模式学习记录-模板方法模式
前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...
- C#设计模式之十三模板方法模式(Template Method Pattern)【行为型】
一.引言 “结构型”的设计模式已经写完了,从今天我们开始讲“行为型”设计模式.现在我们开始讲[行为型]设计模式的第一个模式,该模式是[模板方法],英文名称是:Template Method Patte ...
- 设计模式之七:模板方法模式(Template Method)
模板方法模式: 定义了一个算法的基本操作骨架,并将算法的一些步骤延迟到子类中来实现. 模板方法模式让子类在不更改算法结构的前提下能够又一次定义算法的一些步骤. Define the skeleton ...
- 《Java设计模式》之模板方法模式
模板方法模式是类的行为模式.准备一个抽象类.将部分逻辑以详细方法以及详细构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类能够以不同的方式实现这些抽象方法,从而对剩余的逻辑有 ...
- 设计模式之禅——模板方法模式&钩子方法
** **板方法模式的定义: 定义一个操作的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的框架即可重定义该算法的某些特定步骤. 例子:做一个简单的悍马车的模型 见UML图 一个抽象 ...
随机推荐
- 学习Ant Design Pro的一点心得
1.控制反转(Inversion of Control)是一种「思想」,依赖注入(Dependency Injection)则是这一思想的一种具体「实现方式」 2.react 要注意全局 id相同 3 ...
- postgresql + mybatis insert主键自增方法
postgresql + mybatis插入记录时设置自增主键方法: 一.数据库设置主键自增 1.数据库中id字段选择serial4类型后,会在默认值中生成 nextval('app_id_seq': ...
- Linux之定时任务crond
定时任务说明与分类 定时任务的应用场景举例 每天晚上 12点备份/etc/目录 tar 定时任务的三种分类 crond(crontab)定时任务软件(软件包cronie),用的最多的一种 atd,应用 ...
- 第二十六篇:USB3.0高带宽ISO(48KBytes/125us)实战
USB3.1技术已经推出, 10Gbps的速率足以满足数据, HD视频传输的要求. 要步入USB3.1的研发, 还得将USB3.0的基础打扎实. 微软提供的SUPER MUTT仅仅包括一个接口0, 其 ...
- UVA1616-Caravan Robbers(枚举)
Problem UVA1616-Caravan Robbers Accept: 160 Submit: 1156Time Limit: 3000 mSec Problem Description O ...
- jenkins进行andriod打包,上传蒲公英
环境:macos jenkins sdk gradle 1.构建操作注意: mac电脑上 选择invoke gradle task数值是:clean 2.再创建一个task 然后进行gradle加参数 ...
- 【转】Mysql解决The total number of locks exceeds the lock table size错误
InnoDB表执行大批量数据的更新,插入,删除操作时会出现这个问题,需要调整InnoDB全局的innodb_buffer_pool_size的值来解决这个问题,并且重启mysql服务. windows ...
- HashMap 1.7
1.关键属性与内部类 1.1属性 使用拉链法解决hash冲突的hash表,hash表里存了多少个元素.数组有多长以及当什么情况下需要扩容是重要的参数. transient Entry<K,V&g ...
- 7-EL表达式和JSTL表达式
引入jar包 一.EL表达式1.表达式语言,用于jsp网页中获取和计算数据2.语法:${表达式}3.用于取值:可以从pageContext,request,session,application这些域 ...
- SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)
SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表) swap_join_inputs是针对哈希连接的hint,它的含义 ...