22种设计模式——模板方法模式

模板方法模式是一种行为设计模式,通过在抽象类中定义算法框架,允许子类在不改变结构的情况下重写算法的特定步骤。该模式常用于简化代码结构,减少重复,并在确保算法整体结构不变的情况下,让子类实现细节差异。适用于处理不同格式文件的数据挖掘程序,允许客户端仅重写特定部分的算法,同时避免客户端代码中的条件语句。
摘要由CSDN通过智能技术生成

1. 概述

模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。
在这里插入图片描述
我们说一种设计模式简单,一种是说他的使用场景明确,不会轻易和别的模式弄混,比如单例模式;然而还有一种就是实现简单,模板模式正是后者,它实在不能再简单了,它其实就是抽象类的使用方法。

从问题引入:假如你正在开发一款分析公司文档的数据挖掘程序。 用户需要向程序输入各种格式 (PDF、 DOC 或 CSV) 的文档, 程序则会试图从这些文件中抽取有意义的数据, 并以统一的格式将其返回给用户。

该程序的首个版本仅支持 DOC 文件。 在接下来的一个版本中, 程序能够支持 CSV 文件。 一个月后, 你 “教会” 了程序从 PDF 文件中抽取数据。

在这里插入图片描述
一段时间后, 你发现这三个类中包含许多相似代码。 尽管这些类处理不同数据格式的代码完全不同, 但数据处理和分析的代码却几乎完全一样。 如果能在保持算法结构完整的情况下去除重复代码, 这难道不是一件很棒的事情吗?

还有另一个与使用这些类的客户端代码相关的问题: 客户端代码中包含许多条件语句, 以根据不同的处理对象类型选择合适的处理过程。 如果所有处理数据的类都拥有相同的接口或基类, 那么你就可以去除客户端代码中的条件语句, 转而使用多态机制来在处理对象上调用函数。

那怎么做呢?

  • 低情商:用抽象类就可以了
  • 高情商:用模板方法模式

具体一点来说,其实就是定义一个抽象类,我们都知道抽象类里面可有普通方法和抽象方法,这时普通方法就写子类共有的功能,抽象方法就留给子类重写它们特有的功能。上面的这个例子里,重复的数据处理和分析的代码就可以写到普通方法里,而从不同格式抽离出数据的方法就写成抽象方法,具体子类具体实现这样就OK了。

  • 总结:模板方法模式其实就是一种抽象类的使用方法!!!

2. 特点

  • 优点
    1. 你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
    2. 你可将重复代码提取到一个超类中。
  • 缺点
    1. 部分客户端可能会受到算法框架的限制。
    2. 通过子类抑制默认步骤实现可能会导致违反里氏替换原则。
    3. 模板方法中的步骤越多, 其维护工作就可能会越困难。
  • 使用场景
    1. 当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。

      模板方法将整个算法转换为一系列独立的步骤, 以便子类能对其进行扩展, 同时还可让超类中所定义的结构保持完整。

    2. 当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。

      在将算法转换为模板方法时, 你可将相似的实现步骤提取到超类中以去除重复代码。 子类间各不同的代码可继续保留在子类中。


3. 实现

  • UML类图
    在这里插入图片描述

  • Java代码

    1. 模板类
      /**
       * @Author: chy
       * @Description: 模板类
       * @Date: Create in 10:41 2021/3/24
       */
      public abstract class DataMiner {
          // 定义好的步骤
          void dataAnalyze(){
              System.out.println("数据分析");
          }
      
          // 抽象方法,需要子类实现
          abstract void getData();
      }
      
    2. 具体子类
      /**
       * @Author: chy
       * @Description: 具体子类,从WORD里面获取数据
       * @Date: Create in 10:45 2021/3/24
       */
      public class WORDDataMiner extends DataMiner{
          @Override
          void getData() {
              System.out.println("从WORD里获取数据");
          }
      }
      
      /**
       * @Author: chy
       * @Description: 具体子类,从PDF里面获取数据
       * @Date: Create in 10:44 2021/3/24
       */
      public class PDFDataMiner extends DataMiner{
          @Override
          void getData() {
              System.out.println("从PDF里获取数据");
          }
      }
      
    3. 客户端
      /**
       * @Author: chy
       * @Description: 客户端
       * @Date: Create in 10:40 2021/3/24
       */
      public class Client {
          public static void main(String[] args) {
              PDFDataMiner pdfDataMiner = new PDFDataMiner();
              pdfDataMiner.getData();
              pdfDataMiner.dataAnalyze();
              System.out.println("=============================");
              WORDDataMiner wordDataMiner = new WORDDataMiner();
              wordDataMiner.getData();
              wordDataMiner.dataAnalyze();
          }
      }
      
    4. 结果
      在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值