简介
模板方法模式(Template Method Pattern)又叫作模板模式,指定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤,属于行为型设计模式。
通用模板
-
创建抽象模板:抽象模板类,定义了一套算法框架/流程。
java// 抽象模板类 public abstract class AbstractTemplate { protected void step1(){ System.out.println("AbstractTemplate step1"); } protected void step2(){ System.out.println("AbstractTemplate step2"); } protected void step3(){ System.out.println("AbstractTemplate step3"); } // 生命为final类型,避免子类对其覆写 public final void templateMethod(){ this.step1(); this.step2(); this.step3(); } }
-
创建具体实现类:具体实现类,对算法框架/流程的某些步骤进行了实现。
java// 具体实现类A public class ConcreteA extends AbstractTemplate { @Override public void step1() { System.out.println("ConcreteA step1"); } @Override public void step2() { System.out.println("ConcreteA step2"); } @Override public void step3() { System.out.println("ConcreteA step3"); } }
java// 具体实现类A public class ConcreteB extends AbstractTemplate { @Override public void step1() { System.out.println("ConcreteB step1"); } @Override public void step2() { System.out.println("ConcreteB step2"); } @Override public void step3() { System.out.println("ConcreteB step3"); } }
模板测试
-
测试代码
javapublic class Client { public static void main(String[] args) { AbstractTemplate abc = new ConcreteA(); abc.templateMethod(); abc = new ConcreteB(); abc.templateMethod(); } }
-
结果
javaConcreteA step1 ConcreteA step2 ConcreteA step3 ConcreteB step1 ConcreteB step2 ConcreteB step3
应用场景
当完成一个操作具有固定的流程时,由抽象固定流程步骤,具体步骤交给子类进行具体实现(固定的流程,不同的实现)。
模板方法模式适用于以下应用场景。
(1)一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
(2)各子类中公共的行为被提取出来,集中到一个公共的父类中,从而避免代码重复。
优点
(1)利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
(2)将不同的算法逻辑分离到不同的子类中,通过对子类的扩展增加新的行为,提高代码的可扩展性。
(3)把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。
缺点
(1)每一个抽象类都需要一个子类来实现,这样导致类数量增加。
(2)类数量的增加,间接地增加了系统实现的复杂度。
(3)由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
"生搬硬套"实战
场景描述
假设你是一位烘焙师傅,你经常需要制作各种蛋糕。尽管蛋糕的种类很多,但制作蛋糕的基本步骤是相似的:准备材料、混合材料、烘烤、装饰。这些步骤中有一些是固定的,而另一些可以根据具体的蛋糕种类进行调整。
代码开发
-
创建抽象模板(这里制作蛋糕模板类)
java// 制作蛋糕模板类 public abstract class CakeBakingTemplate { // 模板方法,定义了制作蛋糕的整体流程 public final void bakeCake() { prepareIngredients(); mixIngredients(); bake(); decorate(); } // 抽象方法,子类必须实现 protected abstract void prepareIngredients(); // 默认实现的方法,子类可以选择重写 protected void mixIngredients() { System.out.println("在碗里混合配料。"); } // 默认实现的方法,子类可以选择重写 protected void bake() { System.out.println("在烤箱里烤蛋糕。"); } // 默认实现的方法,子类可以选择重写 protected void decorate() { System.out.println("用糖霜装饰蛋糕。"); } }
-
创建具体实现类(这里是制作巧克力蛋糕和香草蛋糕类)
java// 具体巧克力蛋糕类 public class ChocolateCake extends CakeBakingTemplate { @Override protected void prepareIngredients() { System.out.println("准备巧克力原料。"); } @Override protected void bake() { System.out.println("在350度的温度下烘焙巧克力蛋糕30分钟。"); } @Override protected void decorate() { System.out.println("用巧克力甘纳许装饰巧克力蛋糕。"); } }
java// 香草蛋糕类 public class VanillaCake extends CakeBakingTemplate { @Override protected void prepareIngredients() { System.out.println("准备香草配料。"); } @Override protected void bake() { System.out.println("香草蛋糕在350度烘焙25分钟。"); } @Override protected void decorate() { System.out.println("用香草糖霜装饰香草蛋糕。"); } }
至此,我们就通过"生搬硬套"模板方法模式的模板设计出一套制作蛋糕的模板,接下来我们进行测试:
-
测试代码
javapublic class Client { public static void main(String[] args) { CakeBakingTemplate chocolateCake = new ChocolateCake(); chocolateCake.bakeCake(); CakeBakingTemplate vanillaCake = new VanillaCake(); vanillaCake.bakeCake(); } }
-
结果
java准备巧克力原料。 在碗里混合配料。 在350度的温度下烘焙巧克力蛋糕30分钟。 用巧克力甘纳许装饰巧克力蛋糕。 准备香草配料。 在碗里混合配料。 香草蛋糕在350度烘焙25分钟。 用香草糖霜装饰香草蛋糕。
总结
模板方法模式实际上封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同的实现,从而让固定的流程产生不同的结果。它非常简单,其实就是类的继承机制,但它却是一个应用非常广泛的模式。模板方法模式的本质是抽象封装流程,具体进行实现。