【设计模式】模板模式

 引子

  这是一个很简单的模式,却被很是普遍的使用。算法

  之因此简单是由于在这个模式中仅仅使用到了继承关系。设计模式

  继承关系因为自身的缺陷,被专家们扣上了“罪恶”的帽子。框架

  “使用委派关系代替继承关系”,ide

  “尽可能使用接口实现而不是抽象类继承”等等专家警告,让咱们你们对继承“刮目相看”。测试

  其实,继承仍是有不少自身的优势所在。只是被你们滥用的彷佛缺点更加明显了。编码

  合理的利用继承关系,仍是能对你的系统设计起到很好的做用的。spa

  而模板方法模式就是其中的一个使用范例。设计

定义与结构

  模板方法(Template Method)模式:code

  定义一个操做中的算法的骨架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。blog

  这里的算法的结构,能够理解为你根据需求设计出来的业务流程。

  特定的步骤就是指那些可能在内容上存在变数的环节。

  能够看出来,模板方法模式也是为了巧妙解决变化对系统带来的影响而设计的。

  使用模板方法使系统扩展性加强,最小化了变化对系统的影响。

模板模式结构

  1. 抽象类(Abstract Class):定义了一到多个的抽象方法,以供具体的子类来实现它们;并且还要实现一个模板方法,来定义一个算法的骨架。该模板方法不只调用前面的抽象方法,也能够调用其余的操做,只要能完成自身的使命。
  2. 具体类(Concrete Class):实现父类中的抽象方法以完成算法中与特定子类相关的步骤。

结构图

  直接把《设计模式》上的图拿过来用下

 

  

举例

  JUnit 中的 TestCase 以及它的子类就是一个模板方法模式的例子。

  在 TestCase 这个抽象类中将整个测试的流程设置好了,好比

  1. 先执行 Setup 方法初始化测试前提,
  2. 在运行测试方法,
  3. 而后再 TearDown 来取消测试设置。

  可是你将在 Setup、TearDown 里面做些什么呢?鬼才知道呢!!

  所以,而这些步骤的具体实现都延迟到子类中去,也就是你实现的测试类中。

  来看下相关的源代码吧。

  这是 TestCase 中,执行测试的模板方法。

public void runBare() throws Throwable {
    setUp();
    try {
          runTest();
    }
    finally {
          tearDown();
    }
}
View Code

  你能够看到,里面正像前面定义中所说的那样,它制定了“算法”的框架——先执行 setUp 方法来作下初始化,而后执行测试方法,最后执行 tearDown 释放你获得的资源。

protected void setUp() throws Exception {
}
protected void tearDown() throws Exception {
}
View Code

  这就是上面使用的两个方法。

  与定义中不一样的是,这两个方法并无被实现为抽象方法,而是两个空的无为方法(被称为钩子方法)。

  这是由于在测试中,咱们并非必需要让测试程序使用这两个方法来初始化和释放资源的。

  若是是抽象方法,则子类们必须给它一个实现,无论用到用不到。这显然是不合理的。

  使用钩子方法,则你在须要的时候,能够在子类中重写这些方法。

适用状况

  根据上面对定义的分析,以及例子的说明,能够看出模板方法适用于如下状况

  1. 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以免代码重复。其实这能够说是一种好的编码习惯了。
  3. 控制子类扩展。模板方法只在特定点调用操做,这样就只容许在这些点进行扩展。

  好比上面 runBare()方法就只在 runTest 前面适用 setUp 方法。

  若是你不肯子类来修改你的模板方法定义的框架,你能够采用两种方式来作:

  1. 一是在 API 中不体现出你的模板方法;
  2. 或者将你的模板方法置为 final 就能够了。

  能够看出(优势):

  1. 使用模板方法模式能够将代码的公共行为提取出来,达到复用的目的。
  2. 并且,在模板方法模式中,是由父类的模板方法来控制子类中的具体实现。这样你在实现子类的时候,根本不须要对业务流程有太多的了解。

 

  @成鹏致远

(blogs:lcw.cnblogs.com

(emailwwwlllll@126.com)

(qq552158509)

相关文章
相关标签/搜索