无处不在的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的实现逻辑:

 1 public abstract class DataAccessObject
 2 
 3 {
 4     protected string connectionString;
 5 
 6     protected DataSet dataSet;
 7 
 8     protected virtual void Connect()
 9 
10     { 
11         connectionString = 
12 
13             "Server=.;User Id=sa;Password=;Database=Northwind";
14 
15     }
16 
17    protected  abstract void Select();
18 
19     protected abstract void Display();
20 
21 
22     protected virtual void Disconnect()
23 
24     {
25         connectionString = "";
26     }
27 
28     // The "Template Method" 
29 
30     public void Run()
31 
32     {
33         Connect();
34 
35         Select();
36 
37         Display();
38 
39         Disconnect();
40     }
41 }

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

 1 class Categories : DataAccessObject
 2 
 3 {
 4     protected override void Select()
 5     {
 6         string sql = "select CategoryName from Categories";
 7 
 8         SqlDataAdapter dataAdapter = new SqlDataAdapter(
 9 
10             sql, connectionString);
11 
12         dataSet = new DataSet();
13 
14         dataAdapter.Fill(dataSet, "Categories");
15 
16     }
17 
18     protected override void Display()
19 
20     {
21 
22         Console.WriteLine("Categories ---- ");
23 
24         DataTable dataTable = dataSet.Tables["Categories"];
25 
26         foreach (DataRow row in dataTable.Rows)
27 
28         {
29 
30             Console.WriteLine(row["CategoryName"].ToString());
31 
32         }
33 
34         Console.WriteLine();
35 
36     }
37 }
 1 class Products : DataAccessObject
 2 
 3 {
 4     protected override void Select()
 5 
 6     {
 7         string sql = "select top 10 ProductName from Products";
 8 
 9         SqlDataAdapter dataAdapter = new SqlDataAdapter(
10 
11             sql, connectionString);
12 
13         dataSet = new DataSet();
14 
15         dataAdapter.Fill(dataSet, "Products");
16 
17     }
18 
19     protected override void Display()
20 
21     {
22 
23         Console.WriteLine("Products ---- ");
24 
25         DataTable dataTable = dataSet.Tables["Products"];
26 
27         foreach (DataRow row in dataTable.Rows)
28 
29         {
30             Console.WriteLine(row["ProductName"].ToString());
31 
32         }
33 
34         Console.WriteLine();
35 
36     }
37 
38 }

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

 1 public class App
 2 
 3 {
 4     static void Main()
 5     {
 6 
 7         DataAccessObject dao;
 8 
 9 
10         dao = new Categories();
11 
12         dao.Run();
13 
14 
15         dao = new Products();
16 
17         dao.Run();
18 
19         // Wait for user 
20 
21         Console.Read();
22 
23     }
24 
25 }

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

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方法。

转载于:https://www.cnblogs.com/abcdwxc/archive/2007/09/14/892726.html

模板方法(Template Method)相关推荐

  1. 设计模式--模板方法(Template Method)模式

    模式定义 定义一个操作的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法某些特定步骤 类图 要点总结 Template Method模式是一种非常基础性的设计模式, ...

  2. 咕泡-模板方法 template method 设计模式笔记

    2019独角兽企业重金招聘Python工程师标准>>> 模板方法模式(Template Method) 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中 Template Met ...

  3. 31模板方法(Template Method)

    无处不在的Template Method      如果你只想掌握一种设计模式,那么它就是Template Method! 动机(Motivate):     变化 -----是软件设计的永恒主题,如 ...

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

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

  5. java 模板方法_Java设计模式21:模板方法(Template Method)

    1.功能 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 . 2.模式中的角色 2.1 抽象类(AbstractClass ...

  6. 设计模式:模板方法(Template Method Pattern)

    模板方法模式: 在一个抽象类公开定义了执行它的方法的模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行. 属于行为型模式. spring ioc容器初始化时运用到模板方法模式. / ...

  7. 设计模式-模板方法(Template Method Patten)

    定义一个操作中算法的框架,而将一些步骤延迟到一些子类.使得子类可以不改变一个算法的结构即可重新定义改算法的某些特定步骤 先举一个使用模板方法的小例子方便大家加深印象和理解 首先画下类图 image.p ...

  8. 设计模式六: 模板方法(Template Method)

    简介 模板方法属于行为型模式的一种. 实现层面上, 在抽象类中定义了算法或流程的骨架, 将其中易变的部分延迟到子类实现, 也就是允许它的子类实现其中的某些步骤. 模板方法适用于算法不变, 但算法中某些 ...

  9. 设计模式初探之模板方法(Template Method)

    定义:定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤. 类型:行为类模式 类图: 事实上,模版方法是编程中一个经常用到的模式.先来看一 ...

最新文章

  1. IIS启动配置的一些命令
  2. linux用户层驱动--VFIO(五)
  3. CodeForces - 1373F Network Coverage(二分)
  4. tomcat jar包编译后变成文件夹_tomcat学习|tomcat中的类加载器
  5. extjs年月日时分选择控件_UI设计|网站公共控件及交互事件
  6. Windows常用的网络命令
  7. C语言目录操作 (Linux/Unix)
  8. 带绿色箭头指示的滑动门DIV效果
  9. 机器学习(6): 层次聚类 hierarchical clustering
  10. 市场占比 44%,IDC 最新报告:阿里云智能语音市场排名第一
  11. Python实战之SocketServer模块
  12. openstack nova后端使用ceph rbd(增加在线迁移live_migrate和快照snapshot功能)
  13. teechart的addarray_TeeChart绘图控件 - 之三 - 提高绘图的效率
  14. [game]《泰坦陨落2》
  15. 微信企业号开发:corpsecret到底在哪块呢?
  16. Linux中的多路IO转接,转载
  17. 性能测试工具loucst使用(最新版本)
  18. 【SHOI 2002】百事世界杯之旅 (BSOI4841)
  19. 单音信号对载波信号进行双边带幅度调制
  20. AFL入门学习<AFL 下载和安装>

热门文章

  1. oracle12c备份和恢复,Oracle12c数据的逻辑备份与恢复
  2. xhell 镜像_2020官网下载Xshell 6.0.189.0中文版
  3. 代码流程图_LaTeX 中传统流程图的绘制方法
  4. cordova+vue项目整合
  5. 愤怒的小鸟的html制作,如何做html5山寨版愤怒的小鸟
  6. python课程结课感悟_科学网—《互联网+引论与Python》课堂感想(七) - 张忆文的博文...
  7. 无法打开计算机的组策略,win7系统电脑本地组策略打不开无法运行的解决方法...
  8. 禁止html页面无法粘贴复制,javascript中如何禁止复制粘贴?
  9. php include virtual,虚拟主机中对PHP的特殊设置
  10. mysql按年创建分区表,增加分区表,删除分区表,实战练习