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图 一个抽象 ...
随机推荐
- MacBook Pro维修过程
上个月买了2016款无touchbar的MacBook Pro,这款的键盘跟15年版本的很不一样. 在用了三周左右,就发现有个键按着不灵活了,像是进了水一样,黏住感觉,必须要大力按才会出来.思来想去, ...
- 《Java大学教程》—第5章 数组
5.6 增强的for循环:访问整个数组,读取数组元素,不基于数据下列5.7 数组方法:最大值.求和.成员访问.查找 1.答:P92存储固定个数相同数据类型的一组元素. 2.答:P92所有存储在一个特定 ...
- detail
<!DOCTYPE html> <html> <head> <title>details</title> <style type=&q ...
- python 之常用模块
一 认识模块 二 常用模块 (1)re模块 (2)collections模块 一 认识模块 (1)什么是模块 (2)模块的导入和使用 (1)模块是:一个模块就是一个包含 ...
- B树索引分裂
一.索引分裂 1. 什么是分裂 在开始介绍之前,我们先来搞清楚什么是索引分裂吧.“索引分裂”就是索引块的分裂,当一次DML事务操作修改了索引块上的数据,但是旧有的索引块没有足够的空间来容纳新修改的数 ...
- 8.04-book
import requests from lxml import etree from bs4 import BeautifulSoup import json class BookSpider(ob ...
- UML各种图
UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明.可视化.和编制文档的一种标准语言.下面将对UML的九种图+包图的基本概念进行介绍以及各 ...
- 搭建golang学习环境,并用chrome headless获取网页内容
想用go练练手(我是win7系统,已从https://studygolang.com/dl 下载了go安装包并安装,比较简单,不详述. 但作为边民,没法go get ,又不敢用梯子,幸亏有爱心大牛们的 ...
- 定义静态map
public final static Map<String, String> header = new HashMap<String, String>(); static { ...
- 英文字母对应的Unicode编码
A~Z :65~90 a~z :97~122 0-9 : 48-57 如果想要知道字符串中的值是否是小写英文字符,不使用工具包的一种方法就是使用Unicode编码值,举例: package main ...