模板方法模式(Template Method Pattern)在一个方法中定义一个算法的骨架, 而将一些步骤延迟到子类中. 模板方法使得子类可以在不改变算法结构的情况下, 重新定义算法中的某些步骤,属于行为型模式。

模板方法应用的场景

1、一次性实现一个算法不变的部分,并将可变的行为留给子类来实现;

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

下面我们来看下模板方法模式通用的UML图:

模板方法模式_java

抽象模板(AbstractClass):抽象模板类,定义了一套算法框架/流程;

具体实现(ConcreateClass):具体实现类,对算法框架/流程的某些步骤进行实现。

模板方法的案例

比如我们大家都玩过游戏,是不是需要经过,初始化游戏->开始玩游戏->结束游戏。这就是一个很好的模板方式的案例。

创建Game类:




public abstract class Game {  abstract void init();  abstract void start();  abstract void end();
 public void play(){    //初始化游戏    init();    //开始玩游戏    start();    //结束游戏    end();  }}

创建GloryOfKing王者荣耀类:


public class GloryOfKing extends Game {  @Override  void init() {    System.out.println("初始化王者荣耀游戏");  }
 @Override  void start() {    System.out.println("玩王者荣耀游戏");  }
 @Override  void end() {    System.out.println("退出王者荣耀游戏");  }}

创建LOL英雄联盟类:



public class LOL extends Game {  @Override  void init() {    System.out.println("初始化英雄联盟游戏");  }
 @Override  void start() {    System.out.println("玩英雄联盟游戏");  }
 @Override  void end() {    System.out.println("退出英雄联盟游戏");  }}

测试类:


public class Test {  public static void main(String[] args) {    Game game = new GloryOfKing();    game.play();
   game = new LOL();    game.play();  }}

运行结果:

初始化王者荣耀游戏

玩王者荣耀游戏

退出王者荣耀游戏

初始化英雄联盟游戏

玩英雄联盟游戏

退出英雄联盟游戏

模板方法模式在源码中运用

我们看看JDK中的java.util.AbstractList代码:


/**     * {@inheritDoc}     *     * @throws IndexOutOfBoundsException {@inheritDoc}     */abstract public E get(int index);

这个get()方法是一个抽象方法,它就是交给它的子类来实现,例如java.util.ArrayList就是java.util.AbstractList的子类。还有我们用的HttpServlet有三个方法,service()、doGet()和doPost()方法,都是模板方法抽象的体现。还有其他的例子不胜枚举,有兴趣的话可以多看看源码,如果有什么疑问,可以联系笔者一起探讨。

模板方法的优缺点

 优点:

  1、利用模板模式可以将相同处理逻辑的代码放到抽象父类中,提高了代码的复用性。

  2、将不同的逻辑放到不同的子类中,通过子类的扩展增加新的行为,提高了代码的扩展性。

  3、把不变的行为写在父类中,去除了子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。

 缺点:

  1、每个抽象类都需要至少一个子类来实现,导致了类数量的增加。

  2、类数量增加间接增加了系统的复杂性。

  3、因为继承关系的自身缺点,如果父类添加一个新的抽象方法,有子类都要实现一遍。