目录
模板方法模式定义
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
优点
-
代码复用:模板方法模式允许将通用的算法骨架在父类中定义,从而促进了代码复用。
-
扩展性:子类可以根据需要重写或扩展特定步骤的实现,从而实现了算法的可扩展性。
-
封装性:算法的实现细节被封装在具体子类中,使得客户端只需要关心高层次的模板方法。
缺点
-
复杂性:模板方法模式引入了额外的抽象层次,可能使类结构变得更加复杂。
模板方法模式结构说明
-
抽象模板类(Abstract Template):定义了一个模板方法,该方法包含了算法的骨架,其中某些步骤可能是抽象的或具体的方法。抽象模板类可以包含一些默认的具体实现。
-
具体子类(Concrete Subclass):具体子类继承抽象模板类,并实现抽象方法以完成算法中的具体步骤。
工作流程
-
抽象模板类定义了一个模板方法,该方法包含了算法的骨架,包括一系列步骤。
-
具体子类继承抽象模板类,并实现其中的抽象方法,提供特定步骤的具体实现。
-
客户端通过调用抽象模板类的模板方法来触发算法,该方法按照预定的顺序执行各个步骤。
代码练习
模板方法模式属于行为型设计模式。就像我们平常冲泡咖啡和茶水的情景,都是烧水,冲泡,装杯和加调味品。
1.创建抽象模板类DrinkWater,提供的冲泡流程beverageProcess();
public abstract class DrinkWater { void beverageProcess(){ boilWate(); brew(); pourInCup(); addCondiment(); } abstract void brew(); abstract void addCondiment(); // 有差异的步骤定义为抽象的 void boilWate(){ System.out.println("烧水..."); } void pourInCup(){ System.out.println("装杯..."); } }
2.创建具体子类冲咖啡BeverageCoffee
public class BeverageCoffee extends DrinkWater { @Override void brew() { System.out.println("咖啡就加咖啡伴侣..."); } @Override void addCondiment() { System.out.println("再来点牛奶吧,拿铁刚刚好..."); } }
3.创建具体子类泡茶BeverageTea
public class BeverageTea extends DrinkWater { @Override void brew() { System.out.println("茶水当然放茶包了..."); } @Override void addCondiment() { System.out.println("再来两片柠檬,正好柠檬茶..."); } }
4.客户端代码
public class TemplateClient { public static void main(String[] args) { DrinkWater drinkWater = new BeverageCoffee(); drinkWater.beverageProcess(); System.out.println(); DrinkWater drinkWaterTea = new BeverageTea(); drinkWaterTea.beverageProcess(); } }
应用场景
-
当有一个通用的算法骨架,但不同部分的实现可能会变化时,可以使用模板方法模式。这样可以避免代码重复,并提供一种扩展算法的方式。
-
当需要控制子类的扩展点时,模板方法模式非常有用。父类可以定义哪些方法是必须实现的,哪些方法是可选的。
-
当希望在不改变算法结构的情况下,允许子类重写或扩展特定步骤时,模板方法模式也适用。
本质
模板方法模式的本质是定义一个算法的骨架,将其中某些步骤的实现延迟到子类中。
涉及的设计原则:
开闭原则(Open-Closed Principle):模板方法模式遵循开闭原则,因为它允许在不改变算法结构的情况下扩展或修改算法的特定步骤。
相关设计模式
-
模板方法模式通常与工厂方法模式(Factory Method Pattern)结合使用,工厂方法模式用于创建具体子类的实例,这些子类将实现模板方法中的抽象步骤。此外,模板方法模式与策略模式(Strategy Pattern)也有一些相似之处,因为它们都涉及定义算法的组成部分。不同之处在于,模板方法模式在定义算法的骨架时使用继承,而策略模式使用组合。
开源框架中的应用
-
Java中的Servlet类:Servlet是用于构建Web应用程序的Java组件之一。Servlet规范定义了一种模板方法,即
doGet
和doPost
等方法,开发人员可以通过继承HttpServlet
类并重写这些方法来创建自定义的Servlet。这就是一个模板方法模式的应用。 -
JUnit测试框架:JUnit是一个用于Java应用程序的单元测试框架。在JUnit中,
TestCase
类包含了一个run
方法,该方法定义了运行测试用例的算法骨架。