无处不在的Template Method 
    如果你只想掌握一种设计模式,那么它就是Template Method!
动机(Motivate):
    变化 -----是软件设计的永恒主题,如何管理变化带来的复杂性?设计模式的艺术性和复杂度就在于如何
分析,并发现系统中的变化和稳定点,并使用特定的设计方法来应对这种变化。
意图(Intent):
    定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。                                                        -------《设计模式》GOF
结构图(Struct):
                    
适用性:

1.一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

2.各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke和Johnson所描述过的“重分解以一般化”的一个很好的例子。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

3.控制子类扩展。模板方法只在特定点调用“Hook”操作,这样就只允许在这些点进行扩展。
生活中的例子:
                
代码实现:

假如我们需要简单的读取Northwind数据库中的表的记录并显示出来。对于数据库操作,我们知道不管读取的是哪张表,它一般都应该经过如下这样的几步:

1.连接数据库(Connect)

2.执行查询命令(Select)

3.显示数据(Display)

4.断开数据库连接(Disconnect)

这些步骤是固定的,但是对于每一张具体的数据表所执行的查询却是不一样的。显然这需要一个抽象角色,给出顶级行为的实现。如下图:                                                                                                   
                         
Template Method模式的实现方法是从上到下,我们首先给出顶级框架DataAccessObject的实现逻辑:

    public abstract class DataAccessObject
{
protected string connectionString; protected DataSet dataSet; protected virtual void Connect()
{
connectionString = "Server=.;User Id=sa;Password=;Database=Northwind";
} protected abstract void Select(); protected abstract void Display(); protected virtual void Disconnect()
{
connectionString = "";
} // The "Template Method"
public void Run()
{
Connect(); Select(); Display(); Disconnect();
}
}

显然在这个顶级的框架DataAccessObject中给出了固定的轮廓,方法Run()便是模版方法,Template Method模式也由此而得名。而对于Select()和Display()这两个抽象方法则留给具体的子类去实现,如下图:
                    

    public class Categories : DataAccessObject
{
protected override void Select()
{
string sql = "select CategoryName from Categories"; SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, connectionString); dataSet = new DataSet(); dataAdapter.Fill(dataSet, "Categories");
} protected override void Display()
{
Console.WriteLine("Categories ---- "); DataTable dataTable = dataSet.Tables["Categories"]; foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["CategoryName"].ToString());
} Console.WriteLine();
}
}

    public class Products : DataAccessObject
{
protected override void Select()
{
string sql = "select top 10 ProductName from Products"; SqlDataAdapter dataAdapter = new SqlDataAdapter(sql,connectionString); dataSet = new DataSet(); dataAdapter.Fill(dataSet, "Products");
} protected override void Display()
{
Console.WriteLine("Products ---- "); DataTable dataTable = dataSet.Tables["Products"]; foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["ProductName"].ToString());
} Console.WriteLine();
}
}

再来看看客户端程序的调用,不需要再去调用每一个步骤的方法:

    class Program
{
static void Main(string[] args)
{
DataAccessObject dao; dao = new Categories(); dao.Run(); dao = new Products(); dao.Run(); Console.ReadLine();
}
}

在上面的例子中,需要注意的是:

1.对于Connect()和Disconnect()方法实现为了virtual,而Select()和Display()方法则为abstract,这是因为如果这个方法有默认的实现,则实现为virtual,否则为abstract。

2.Run()方法作为一个模版方法,它的一个重要特征是:在基类里定义,而且不能够被派生类更改。有时候它是私有方法(private method),但实际上它经常被声明为protected。它通过调用其它的基类方法(覆写过的)来工作,但它经常是作为初始化过程的一部分被调用的,这样就没必要让客户端程序员能够直接调用它了。

3.在一开始我们提到了不管读的是哪张数据表,它们都有共同的操作步骤,即共同点。因此可以说Template Method模式的一个特征就是剥离共同点。
Template Mehtod实现要点:

1.Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。

2.除了可以灵活应对子步骤的变化外,“不用调用我,让我来调用你(Don't call me ,let me call you)”的反向控制结构是Template Method的典型应用。“Don’t call me.Let me call you”是指一个父类调用一个子类的操作,而不是相反。

3.在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法,纯虚方法),但一般推荐将它们设置为protected方法。

13.模板方法(Template Method)的更多相关文章

  1. 行为型设计模式之模板方法(TEMPLATE METHOD)模式 ,策略(Strategy )模式

    1 模板方法(TEMPLATE METHOD)模式: 模板方法模式把我们不知道具体实现的步聚封装成抽象方法,提供一些按正确顺序调用它们的具体方法(这些具体方法统称为模板方法),这样构成一个抽象基类.子 ...

  2. 宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)

    本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前言 <设计模式>这本经典 ...

  3. 模板方法(Template Method)(父类声明算法骨架,子类具体不同实现)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述模板方法(Template Method)模式的: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式 ...

  4. 一天一个设计模式——模板方法(Template Method)模式

    一.模式说明 现实世界中的模板是用于将事物的结构规律予以固定化.标准化的成果,它体现了结构形式的标准化.例如镂空文字印刷的模板,通过某个模板印刷出来的文字字体大小都是一模一样,但是具体使用什么材质的颜 ...

  5. 设计模式13:Template Method 模板方法模式(行为型模式)

    Template Method 模板方法模式(行为型模式) 变与不变 变化——是软件永恒的主题,如何管理变化带来的复杂性?设计模式的艺术性和复杂度就在于如何分析,并发现体系中的变化点和稳定点,并使用特 ...

  6. 设计模式之---模板方法template method的使用

    在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的.Template Method ...

  7. 封装算法: 模板方法(Template Method)模式

    template method(模板方法)模式是一种行为型设计模式.它在一个方法中定义了算法的骨架(这种方法被称为template method.模板方法),并将算法的详细步骤放到子类中去实现.tem ...

  8. 设计模式二--模板方法Template method

    模式分类: 书籍推荐:重构-改善既有代码的设计 重构获得模式 设计模式:现代软件设计的特征是"需求的频繁变化".设计模式的要点是 "寻找变化点,然后在变化点处应用设计模式 ...

  9. C#设计模式——模板方法(Template Method)

    一.概述在软件开发中,对某一项操作往往有固定的算法结构,而具体的子步骤会因为不同的需要而有所不同.如何可以在稳定算法结构的同时来灵活应对子步骤变化的需求呢?二.模板方法模板方法是一种常见的设计模式,它 ...

  10. 设计模式之模板方法(Template Method)

    在整理模板方法之前,先来说点废话吧.除了记录学习总结,也来记录一下生活吧. 我们公司的老板在北京,老板也会因为项目来公司,不过不是天天来.公司有个同事,只要老板不在就天天迟到,而且一天比一天晚,经常来 ...

随机推荐

  1. win10安装MySql 5.7.23

    下载安装 因为Django2.1不再支持MySQL5.5,这里需要重新安装一下MySQL 首先去官网下载 这里使用的是msi版本 https://dev.mysql.com/downloads/win ...

  2. Matplotlib学习---用matplotlib画雷达图(radar chart)

    雷达图常用于对多项指标的全面分析.例如:HR想要比较两个应聘者的综合素质,用雷达图分别画出来,就可以进行直观的比较. 用Matplotlib画雷达图需要使用极坐标体系,可点击此链接,查看对极坐标体系的 ...

  3. 阿里云.log

    申请证书审核失败的原因及处理方法;( 新添加站点 免费版 SSL 网页内不能有 HTTPS的连接:更多点击连接)

  4. redis在centos7下安装

    https://blog.csdn.net/wzygis/article/details/51705559 1.redis下载地址:http://www.redis.cn/download.html ...

  5. Integer’s Power HDU - 3208(容斥原理)

    找出(l,r)内的所有的指数最大的次方和 因为一个数可能可以看成a^b和c^d,所以我需要去重,从后往前枚举幂数,然后找可以整除的部分,把低次幂的数去掉. 然后开n方的部分,先用pow()函数找到最接 ...

  6. BZOJ3029守卫者的挑战(概率dp)

    题目大意:给定n个事件,第i个事件发生的概率为pi,收益为ai,初始收益为k,求n个事件之后发生的事件数>=l且收益>=0的概率 收益只可能是正整数或-1. Solution dp[i][ ...

  7. 2017蓝桥杯 省赛C题(承压计算)

    X星球的高科技实验室中整齐地堆放着某批珍贵金属原料. 每块金属原料的外形.尺寸完全一致,但重量不同.金属材料被严格地堆放成金字塔形. 7 5 8 7 8 8 9 2 7 2 8 1 4 9 1 8 1 ...

  8. 使用Disruptor实现生产者和消费者模型

    生产者 package cn.lonecloud.procum.disruptor; import cn.lonecloud.procum.Data; import com.lmax.disrupto ...

  9. MacBook上使用ssh localhost被拒绝

    最开始以为没有装sshd呢,实际上不是.又查了些方法,有些人居然把Linux上访问失败的方法直接照搬,让我建立公私钥.都没有成功.最后找到了解决方法,原来是由于苹果的安全限制,限制了这个功能. sud ...

  10. 【模板】ac自动机

    本来是真的特别不想写这个的 但是有段时间洛谷天天智推这个可能是我太菜了 然后觉得这个也不难 乘着今早没事写下 来这保存下 方便下次食用 #include <bits/stdc++.h> u ...