前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >模板方法模式浅析

模板方法模式浅析

作者头像
孟君
发布2020-04-22 16:32:29
4270
发布2020-04-22 16:32:29
举报
文章被收录于专栏:孟君的编程札记

在开始本文之前,我们先来看下生活中的一些场景,比如造房子。有一个基本的骨架,每栋房子又可以有自己的特点,比如加个旗子,加一个塔楼等。

这样定义一个操作的骨架,然后将一些步骤延迟到子类中去实现的场景就是我们今天要讲的模板方法模式要做的事情。

一. 模板方法的基本介绍

意图

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

结构

模板方法的基本结构如下:

这里涉及到两个角色:

  • 抽象类(AbstarctClass)
    • 定义一个或者多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤
    • 定义并实现一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能有一些具体方法。
  • 具体类(ConcreteClass)
    • 实现父类定义的一个或者多个抽象方法,它们是一个顶级逻辑的组成步骤。
    • 每个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级的实现各不相同。

模板方法中的方法可以分为两大类:

模板方法(template method)和基本方法(Primitive method)

  • 模板方法
    • 一个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模板方法一般会在抽象类中定义,并由子类不加以修改地完全继承下来,所以在java中使用final来进行修饰。
    • 一个抽象类可以有任意多个模板方法,而不限于一个。每个模板方法都可以调用任意多个具体方法。
  • 基本方法
    • 抽象方法:一个抽象方法由抽象类声明,由具体子类实现,方法使用abstract关键字修饰
    • 具体方法:一个具体方法由抽象类声明并实现,而子类并不实现。一个具体方法没有abstract关键字
    • 钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空的实现,作为方法的默认实现。

二. 模板方法的示例

示例描述

模拟读取不同文件格式,然后输出读取内容的场景。每个处理包括验证文件、解析文件数据、展示数据内容的通用步骤。

  • 定义一个抽象类AbstractHandler
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public abstract class AbstarctHandler {
  
    /**模板方法**/
  public final void process(String filepath) {
    begin();
    
    validate(filepath);
    parseData(filepath);
    display(filepath);
    
    end();
  }
  
  /**抽象方法子类实现**/
  public abstract void validate(String filepath);
  public abstract void parseData(String filepath);
  public abstract void display(String filepath);
  
  /**钩子方法**/
  public void hookMethod() {}
  
  /**具体方法**/
  public void concreteMethod() {}
  public void begin() {
    System.out.println("**************************Begin*************************** ");
  }
  public void end() {
    System.out.println("**************************End*************************** ");
  }
}
  • 定义多个具体类
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public class CsvHanlder extends AbstarctHandler {

  @Override
  public void validate(String filepath) {
    System.out.println("CSV validate ... ... ");

  }

  @Override
  public void parseData(String filepath) {
    System.out.println("CSV pasre data ... ... ");

  }

  @Override
  public void display(String filepath) {
    System.out.println("CSV dispaly ... ... ");

  }

}

PdfHanlder类

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public class PdfHanlder extends AbstarctHandler {

  @Override
  public void validate(String filepath) {
    System.out.println("PDF validate ... ... ");

  }

  @Override
  public void parseData(String filepath) {
    System.out.println("PDF pasre data ... ... ");

  }

  @Override
  public void display(String filepath) {
    System.out.println("PDF dispaly ... ... ");

  }

}

Excel2003Hanlder类

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public class Excel2003Hanlder extends AbstarctHandler {

  @Override
  public void validate(String filepath) {
    System.out.println("Excel 2003 validate ... ... ");

  }

  @Override
  public void parseData(String filepath) {
    System.out.println("Excel 2003 pasre data ... ... ");

  }

  @Override
  public void display(String filepath) {
    System.out.println("Excel 2003 dispaly ... ... ");

  }

}

Excel2007Hanlder类

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public class Excel2007Hanlder extends AbstarctHandler {

  @Override
  public void validate(String filepath) {
    System.out.println("Excel 2007+ validate ... ... ");

  }

  @Override
  public void parseData(String filepath) {
    System.out.println("Excel 2007+ pasre data ... ... ");

  }

  @Override
  public void display(String filepath) {
    System.out.println("Excel 2007+ dispaly ... ... ");

  }

}
  • 编写一个测试类
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.template;

public class Main {

  public static void main(String[] args) {
    AbstarctHandler handler = new CsvHanlder();
    handler.process("xxx.csv");

    System.out.println();

    handler = new PdfHanlder();
    handler.process("xxx.pdf");

    System.out.println();

    handler = new Excel2003Hanlder();
    handler.process("xxx.xls");

    System.out.println();

    handler = new Excel2007Hanlder();
    handler.process("xxx.xlsx");

  }

}

输出结果:

代码语言:javascript
复制
**************************Begin*************************** 
CSV validate ... ... 
CSV pasre data ... ... 
CSV dispaly ... ... 
**************************End*************************** 

**************************Begin*************************** 
PDF validate ... ... 
PDF pasre data ... ... 
PDF dispaly ... ... 
**************************End*************************** 

**************************Begin*************************** 
Excel 2003 validate ... ... 
Excel 2003 pasre data ... ... 
Excel 2003 dispaly ... ... 
**************************End*************************** 

**************************Begin*************************** 
Excel 2007+ validate ... ... 
Excel 2007+ pasre data ... ... 
Excel 2007+ dispaly ... ... 
**************************End***************************

从上述的输出结果,我们可以看到每个不同类型的处理都具有相同的步骤,但是每个步骤有不同的处理。

三. 小结

模板方法模式 vs. 策略模式

比较

在Template Method模式中,可以使用继承改变程序的行为。这是因为Template Method模式在父类定义程序行为的框架,在子类中决定具体的处理。

与此相对的是Strategy模式,它可以使用委托改变程序的行为。与TemplateMethod模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法

之前的策略模式博文 -- 策略模式浅析

参考

[1]. https://refactoring.guru/design-patterns/template-method

[2]. 阎宏. Java与模式.电子工业出版社

[3]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 模板方法的基本介绍
  • 二. 模板方法的示例
  • 三. 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档