23种设计模式-模板方法模式

模板模式

简介

​ 参考文档:https://en.wikipedia.org/wiki/Template_method_pattern

​ 通常叫模板方法模式定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现。

​ 能够使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

​ 属于行为性设计模式

适用场景

​ 一次性实现一个算法的不变的部分,并将可变的部分交给子类来实现

​ 各子类中公共的行为被提取出来并集中到一个公共的父类当中,从而避免代码重复

优点

​ 1、利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
​ 2、将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
​ 3、把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,
符合开闭原则。

缺点

1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
2、类数量的增加,间接地增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍

案例

一个小偷偷东西一般分成几个步骤:

  • 寻找目标
  • 迷惑目标
  • 下手

所以我们先定义一个小偷

public class HalflingThief {

  private StealingMethod method;

  public HalflingThief(StealingMethod method) {
    this.method = method;
  }

  public void steal() {
    method.steal();
  }

  public void changeMethod(StealingMethod method) {
    this.method = method;
  }
}

​ 因为小偷偷东西都是几个固定步骤,所以我们使用模板方法,但是下手的过程有多种方式,所以开放钩子steal方法

/**
 * 
 * StealingMethod defines skeleton for the algorithm.
 * 
 */
public abstract class StealingMethod {

  private static final Logger LOGGER = LoggerFactory.getLogger(StealingMethod.class);

  protected abstract String pickTarget();

  protected abstract void confuseTarget(String target);

  protected abstract void stealTheItem(String target);

  /**
   * Steal
   */
  public void steal() {
    String target = pickTarget();
    LOGGER.info("The target has been chosen as {}.", target);
    confuseTarget(target);
    stealTheItem(target);
  }
}

撞击然后开溜

public class HitAndRunMethod extends StealingMethod {
  
    private static final Logger LOGGER = LoggerFactory.getLogger(HitAndRunMethod.class);
  
    @Override
    protected String pickTarget() {
      return "old goblin woman";
    }
  
    @Override
    protected void confuseTarget(String target) {
      LOGGER.info("Approach the {} from behind.", target);
    }
  
    @Override
    protected void stealTheItem(String target) {
      LOGGER.info("Grab the handbag and run away fast!");
    }
  }

偷偷摸摸的干活

  • public class SubtleMethod extends StealingMethod {
    
      private static final Logger LOGGER = LoggerFactory.getLogger(SubtleMethod.class);
    
      @Override
      protected String pickTarget() {
        return "shop keeper";
      }
    
      @Override
      protected void confuseTarget(String target) {
        LOGGER.info("Approach the {} with tears running and hug him!", target);
      }
    
      @Override
      protected void stealTheItem(String target) {
        LOGGER.info("While in close contact grab the {}'s wallet.", target);
      }
    }
    

测试

/**
 * 
 * Template Method defines a skeleton for an algorithm. The algorithm subclasses provide
 * implementation for the blank parts.
 * <p>
 * In this example {@link HalflingThief} contains {@link StealingMethod} that can be changed. First
 * the thief hits with {@link HitAndRunMethod} and then with {@link SubtleMethod}.
 * 
 */
public class App {

  /**
   * Program entry point
   * 
   * @param args command line args
   */
  public static void main(String[] args) {
    HalflingThief thief = new HalflingThief(new HitAndRunMethod());
    thief.steal();
    thief.changeMethod(new SubtleMethod());
    thief.steal();
  }
}

23种设计模式-模板方法模式

源码中的提现

JDBCTemplate

23种设计模式-模板方法模式

获取连接和关闭链接都已经写好了

23种设计模式-模板方法模式

处理结果集的地方开放

模板和策略的区别:

​ 模板子类能干预实现,但是基础流程已经定下来了

​ 策略不能干预流程,实现方式只能去选择

代码地址:https://gitee.com/zzy0_0/learning/tree/master/src/main/java/cn/zzjson/design/template