模板方法

定义

在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

使用场景

  • 仅需一次实现算法的不变部分,将可以变化的行为留给子类加以实现
  • 当子类中的公共行为应该被考虑并且被定位在公共类中以避免代码重复。 这是Opydke和Johnson所描述的“重构泛化”的好例子。 首先确定现有代码中的差异,然后将差异分为新操作,最后使用调用这些新操作之一的模板方法替换不同的代码
  • 为了控制子类扩展,你可以定义一个模板方法,在特定点调用“钩子”操作,从而只允许在这些点进行扩展

例子

一个刚入门的小偷偷东西,基本上的步骤是: 1. 找到一个目标对象,2. 迷惑他, 3. 偷东西。不论要偷的对象是个老太太,或是个彪壮大汉,步骤是不变的;只是迷惑和偷的方法不一样。
定义小偷偷东西方法的模板

public abstract class StealingMethod {
  protected abstract String pickTarget();   // 选取目标
  protected abstract void confuseTarget(String target); // 迷惑对方
  protected abstract void stealTheItem(String target);  // 偷东西

  // 偷东西的整个流程
  public void steal() {
    String target = pickTarget();
    System.out.println("The target has been chosen as " + target + ".");
    confuseTarget(target);
    stealTheItem(target);
  }
}

然后两种偷东西的方法实现:

// 对老太太 抢了就跑
public class HitAndRunMethod extends StealingMethod {
  protected String pickTarget() {
    return "old goblin woman";
  }

  protected void confuseTarget(String target) {
    System.out.println("Approach the " + target + " from behind.");
  }

  protected void stealTheItem(String target) {
    System.out.println("Grab the handbag and run away fast!");
  }
}

// 对彪壮大汉 假装自己害怕往他身上靠 趁机偷
public class SubtleMethod extends StealingMethod {
  protected String pickTarget() {
    return "shop keeper";
  }

  protected void confuseTarget(String target) {
    System.out.println("Approach the " + target + " with tears running and hug him!");
  }

  protected void stealTheItem(String target) {
    System.out.println("While in close contact grab the " + target + "'s wallet.");
  }
}

来一个小偷,他会按照特定的偷东西方法去实行,也可以根据对象改变偷的方法:

// 初级小偷对象 会两种偷的方法
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;
  }
}

偷一个试试吧:

// 测试
public class App {
  public static void main(String[] args) {
    HalflingThief thief = new HalflingThief(new HitAndRunMethod());
    thief.steal();
    thief.changeMethod(new SubtleMethod());
    thief.steal();
  }
}

分析

模板方法体现了一个设计原则:别调用我,我会调用你们,也就是好莱坞原则。观察者模式也是这种设计模式的一个典型实现。这个原则来源于好莱坞的演员和电影公司的关系。正常情况演员会在公司登记,公司在有新片机会的时候会联系他们,而不是演员一直打电话问公司有没有机会。

模板方法和策略模式的区别: 模板方法是定义一个算法框架,让基类对象安装这个执行;策略模式是提供一些可以互相替换的算法让对象选择。

参考

iluwatar/java-design-patterns

你可能感兴趣的:(模板方法)