您的位置:首页 > 其它

模板方法模式(Template Pattern)

2016-09-12 13:57 218 查看
1. 概述

  定义一个操作中的算法的骨架,而将步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。

2. 模式中的角色

  2.1 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。
  2.2 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

3.类图



4.代码示例

实际项目中功能类似的页面查询,如查询订单,或者不同状态的实例列表等等,通过下面一个例子能更好的理解模板方法模式:

public abstract class Template {
/**
* 模板方法
* 定义了这个业务逻辑的步骤,作为统一的入口
*/
public final void templateMethod(){
//1.通用的参数校验
check();
//2.查询数据,子类根据自身的逻辑查询数据
queryData();
//3.排序,提供默认的排序方法
sort();
//4.分页
if(needPage()){
page();
}
// …………
}

private void check(){
System.out.println("接口参数校验成功");
}
protected void sort(){
System.out.println("模板方法提供默认的排序规则");
}
protected void page(){
System.out.println("模板方法提供默认的分页规则");
}
protected boolean needPage(){
return true;
}
protected abstract void queryData();
}

2个具体子类:

public class ConcreteA extends Template{

@Override
protected void queryData() {
System.out.println("根据A的规则查询数据");
}

protected void page(){
System.out.println("ConcreteA 分页");
}
}

public class ConcreteB extends Template{

@Override
protected void queryData() {
System.out.println("根据B的规则查询数据");
}

protected void sort(){
System.out.println("ConcreteB 排序");
}

protected boolean needPage(){
return false;
}
}


测试方法:

public static void main(String[] args) {
System.out.println("A:");
Template a = new ConcreteA();
a.templateMethod();
System.out.println("-------------------");
System.out.println("B:");
Template b = new ConcreteB();
b.templateMethod();

}


执行结果:

A:

接口参数校验成功

根据A的规则查询数据

模板方法提供默认的排序规则

ConcreteA 分页

-------------------

B:

接口参数校验成功

根据B的规则查询数据

ConcreteB 排序

在这个例子中,父类定义了一套模板方法,阐明了整个业务逻辑包括校验、查询、排序、分页等步骤。

具体子类实现了父类的抽象方法,完成了查询数据的功能,同时A重写了分页方法,B重写了分页方法。

由测试结果来看,子类重写了父类的钩子方法,从而得到了不同的运行结果。

5.对模板方法模式的行为理解

1.模板方法

模板方法存在于父类中,通常是一个抽象类(java 8中接口也能实现方法),将一些复杂流程的实现步骤封装在一系列基本方法中,定义了统一的逻辑。

2.基本方法

基本方法是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。

2.1抽象方法:一个抽象方法由抽象类声明、由其具体子类实现,如本例中的父类queryData()方法。

2.2具体方法:父类或子类中完成具体功能的方法,如check()、sort()、page()方法。

2.3钩子方法:父类中声明过,子类重写的方法,通常用来由子类控制行为的方法,如needPage()方法。

钩子方法的用法,通常来说有2种:

一种用来控制逻辑,如needPage()方法,返回一个布尔类型来控制是否需要执行分页方法。这里父类默认是true需要分页,若子类不需要分页,则重新该方法返回false,如ConcreteB就是这样做的。这种用法很常见也很重要,假设要在模板方法中加入一个剔除元素的方法,而有些子类不需要这个方法的话,就需要在父类中定义一个钩子方法,默认为false来控制这个具体方法,这样就不需要改变原有的具体子类,而需要改方法的子类可以重写钩子方法返回true就能使用剔除元素的方法了。

另一种是提供默认实现,同时也允许子类重写,使用子类自身逻辑的方法,如果sort()方法。父类中提供了默认实现,也可以是空方法,子类可以有选择的重写。

6.优点:

  1 模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。

  2 子类实现算法的某些细节,有助于算法的扩展。

  3 通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。

7.缺点

  每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。

8.适用场景

  1 在某些类的算法中,用了相同的方法,造成代码的重复。

  2 控制子类扩展,子类必须遵守算法规则。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  template 模板方法