博客信息

模板模式Template(行为模式)

发布时间:『 2019-03-29 22:54』  博客类别:23种设计模式  阅读(680)
  • 术语

    template:模板

模板模式UML类图


小李飞刀_设计模式



  • 角色

    AbstractClass 抽象类实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法 ConcreteClass 2)实现抽象方法 , 以完成算法中特点子类的步骤

  • 案例

    需求:统计某一代码运行时间

    • 使用前

    package com.javaxl.design.template.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-24 15:42
    */
    public class CodeTotalTime {

      public static void template(){
          long start = System.currentTimeMillis();
          //       检测Operation_1方法运行的时长======33
          Operation_1();
          //       检测Operation_2方法运行的时长======616
          //       Operation_2();
          long end = System.currentTimeMillis();
          System.out.println(end-start);
      }

      public static void Operation_1(){

          for (int i = 0; i<1000 ;i++){
              System.out.println("模拟耗时操作...");
          }
          System.out.print("检测Operation_1方法运行的时长======");
      }

      public static void Operation_2(){

          for (int i = 0; i<20000 ;i++){
              System.out.println("模拟耗时操作...");
          }

          System.out.print("检测Operation_2方法运行的时长======");
      }

    }


    public class Client {
      public static void main(String[] args) {
          CodeTotalTime.template();
      }
    }

    • 使用后

package com.javaxl.design.template.after;

/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create  2020-02-24 15:51
* <p>
* 统计代码执行时长的抽象类
*/
public abstract class CodeAbstractClass {

  public void template() {
      long start = System.currentTimeMillis();
      method();
      long end = System.currentTimeMillis();
      System.out.println("当前方法执行时长:"+(end - start));
  }

  public abstract void method();

}

class ConcreteClassA extends CodeAbstractClass{

  @Override
  public void method() {
      for (int i = 0; i<1000 ;i++){
          System.out.println("模拟耗时操作...");
      }
      System.out.print("检测ConcreteClassA.method方法运行的时长======");
  }
}

class ConcreteClassB extends CodeAbstractClass{

  @Override
  public void method() {
      for (int i = 0; i<20000 ;i++){
          System.out.println("模拟耗时操作...");
      }
      System.out.print("ConcreteClassB.method方法运行的时长======");
  }
}


public class Client {
  public static void main(String[] args) {
      //检测ConcreteClassA.method方法运行的时长======当前方法执行时长:40
//       new ConcreteClassA().template();
      //ConcreteClassB.method方法运行的时长======当前方法执行时长:272
      new ConcreteClassB().template();
  }
}

钩子函数应用场景:

public abstract class CodeAbstractClass {

  public void template() {
      long start = System.currentTimeMillis();
      if (callback()) method();
      long end = System.currentTimeMillis();
      System.out.println("当前方法执行时长:" + (end - start));
  }

  public abstract void method();

  public boolean callback() {
      return true;
  }

}

从上面可以看出:template方法默认是用作统计method方法的执行时长,但是有的时候我们无需统计代码时长,template函数中有一些其它逻辑要执行,在这里我们可以考虑采用钩子函数;钩子函数被子类覆写,覆写成false,那么method方法就不会被调用,不再统计代码时长了;前端框架Vue的生命周期就有多处用到钩子函数;

  • 注意事项和细节

    • 钩子函数 在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”

    • 算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改

    • 一般模板方法都加上 final 关键字, 防止子类重写模板方法

  • 应用

    Spring IOC容器加载



总结

  模板非常容易理解,使用起来也很简单,但是在工程中我们往往将模板与其他模式结合起来,因此我们要认清模板的本质,将具有相同操作的多种事物抽象出这些相同的操作,然后将这些操作有机的整合起来变成模板类,另外也要注意在模板方法的定义final表示此方法不能被继承和重写,这无疑是重要的,规定和法则不能被其他人所改变


关键字:     设计模式  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有