模板方法

2021-12-02  本文已影响0人  zhemehao819

1、简介

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

实际上是封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同实现,从而让固定的流程产生不同的结果。其实就是类的继承机制。

本质:抽象封装流程,具体进行实现

2、主要解决

当完成一个操作具有固定的流程时,由抽象固定流程步骤,具体步骤交给子类进行具体实现(固定的流程,不同的实现)。

3、优缺点

优点

缺点

4、使用场景

5、模式讲解

通用 UML 类图:

image

主要包含两种角色:

以下是 模板方法模式 的通用代码:

class Client {
    public static void main(String[] args) {
        AbstractClass abc = new ConcreteClassA();
        abc.templateMehthod();
        abc = new ConcreteClassB();
        abc.templateMehthod();
    }

    // 抽象模板类
    static abstract class AbstractClass {
        protected void step1() {
            System.out.println("AbstractClass:step1");
        }

        protected void step2() {
            System.out.println("AbstractClass:step2");
        }

        protected void step3() {
            System.out.println("AbstractClass:step3");
        }

        // 声明为final方法,避免子类覆写
        public final void templateMehthod() {
            this.step1();
            this.step2();
            this.step3();
        }
    }

    // 具体实现类A
    static class ConcreteClassA extends AbstractClass {
        @Override
        protected void step1() {
            System.out.println("ConcreateClassA:step1");
        }
    }

    // 具体实现类B
    static class ConcreteClassB extends AbstractClass {
        @Override
        protected void step2() {
            System.out.println("ConcreateClassB:step2");
        }
    }
}

:通常把抽象模板类AbstractClass的模板方法templateMethod定义成final类型,避免子类对其覆写,并遵命定义算法结构/流程的语义。

举个例子

例子:程序员每天上班的干活过程。
分析:
开机-->写代码-->关机。整个流程是固定的,可以抽象出来定义一个流程;
其中,对于不同类型的程序员“写代码”这个步骤是不同的,java程序员写java代码,Php程序员写Php代码;开机和关机是完全相同的。

抽象一个父类定义这个流程:

public abstract class Work {
  //定义算法步凑流程
  public void workDay(){
    //1上班开机
    openComputer();
    //2写代码
    coding();
    //3:下班关机     
    closeComputer();
  }

  //开机
  private final void openComputer() {
    System.out.println("到达公司,开机");
  }

  //写代码
  protected abstract void coding();

  //关机
  private final void closeComputer() {
    System.out.println("下班,关机");
  }
}

具体实现
Java程序员:

public class JavaProgrammer extends Work {
  @Override
  protected void coding() {
    System.out.println("Java程序员打开Idea,写Java代码。。。");
  }
}

PHP程序员:

public class PhpProgrammer extends Work {
  @Override
  protected void coding() {
    System.out.println("PHP程序员打开Zend Studio,写Php代码。。。");
  }
}

使用

public class TemplateMethodDemo {
  public static void main(String[] args) {
    Work javaProgrammer = new JavaProgrammer();
    javaProgrammer.workDay();
    System.out.println("================");
    Work phpProgrammer = new PhpProgrammer();
    phpProgrammer.workDay();
  }
}

结果如下:

到达公司,开机
Java程序员打开Idea,写Java代码。。。
下班,关机
================
到达公司,开机
PHP程序员打开Zend Studio,写Php代码。。。
下班,关机

6、模板模式在各源码中体现

(1)每天都在使用的HttpServlet里面的service方法,service方法里面定义了调用流程,根据客户端调用的不同方式,if else逻辑判断调用不同的方法,比如doGet,doPost,doDelete等实现restful调用,具体的doGet,doPost方法实现我们可以在我们自己定义的Servlet中进行重写。

(2)Mybatis框架中也有一些经典实用,比如BaseExecutor类,它是一个基础的SQL执行类,实现了大部分SQL的执行逻辑,然后把几个方法教给子类定制化完成,其中doUpdate(),doFlushStatements(),doQuery(),doQueryCursor()等方法都是由子类来实现的.

上一篇 下一篇

猜你喜欢

热点阅读