原文: https://howtodoinjava.com/design-patterns/behavioral/template-method-pattern/

模板方法设计模式是广泛接受的行为型设计模式,用于在编程的上下文中实现某种算法(固定的步骤集)。

它定义了执行多步算法的顺序步骤,并且还可以选择提供默认实现(根据要求)。

  1. Table of Contents
  2. Introduction
  3. Problem Statement
  4. Solution
  5. Code Implementation
  6. Key Design Points
  7. Popular implementations of template method pattern
  8. Summary

介绍

您是否在编程中遇到过任何情况,每次都需要以固定顺序定义一组特定步骤,以便可以由实现类强制执行? 如果是这样,那么模板方法模式是适合您的解决方案,可用于有序执行这些步骤(算法)。

模板方法模式的适用性

  • 当我们有预定义的步骤来实现一些算法时。
  • 当我们要避免重复代码时,请在基类中移动通用实现和步骤。

现在,让我们解决一个设计问题以详细了解它。

问题陈述

可以说,我们需要建造通常有某些步骤的任何房屋。 有些步骤具有默认实现,而某些步骤是针对没有默认实现的实现者的。

默认实现的步骤

  • 基础建设
  • 屋顶施工

默认实现为“否”的步骤

  • 墙的建造
  • 门窗施工
  • 绘画
  • 室内装修

我们希望通过应用中的所有实现类依次执行这些步骤

解决方案

在上述问题中,我们按照固定顺序采取了某些步骤,所有建筑类别都必须遵循这些步骤。 因此,我们可以使用模板方法设计模式来解决此问题。

让我们定义一个将所有步骤作为方法的基类House,将一个将依次调用中间步骤的模板方法 buildhouse()定义为基类。

我们还将根据房屋的类型(例如GlassWallHouseConcreteWallHouse)创建派生类。

类图

模板方法设计模式 - 图1

使用模板方法设计模式的类图

代码实现

首先,我们需要创建一个名为House的抽象类,它将定义名为buildHouse()的模板方法。

House.java

  1. package com.howtodoinjava.designpattern.template;
  2. /**
  3. * abstract class House containing template method buildHouse and implementation
  4. * of steps which is same for all types of houses. Those implementations have
  5. * been marked as final.
  6. */
  7. public abstract class House {
  8. /**
  9. * This is the template method we are discussing. This method should be
  10. * final so that other class can't re-implement and change the order of the
  11. * steps.
  12. */
  13. public final void buildhouse() {
  14. constructBase();
  15. constructRoof();
  16. constructWalls();
  17. constructWindows();
  18. constructDoors();
  19. paintHouse();
  20. decorateHouse();
  21. }
  22. public abstract void decorateHouse();
  23. public abstract void paintHouse();
  24. public abstract void constructDoors();
  25. public abstract void constructWindows();
  26. public abstract void constructWalls();
  27. /**
  28. * final implementation of constructing roof - final as all type of house
  29. * Should build roof in same manner.
  30. */
  31. private final void constructRoof() {
  32. System.out.println("Roof has been constructed.");
  33. }
  34. /**
  35. * final implementation of constructing base - final as all type of house
  36. * Should build base/foundation in same manner.
  37. */
  38. private final void constructBase() {
  39. System.out.println("Base has been constructed.");
  40. }
  41. }

现在,我们将创建该类的两个实现,可用于建造具体房屋和玻璃房屋。

ConcreteWallHouse.java

  1. package com.howtodoinjava.designpattern.template;
  2. public class ConcreteWallHouse extends House {
  3. @Override
  4. public void decorateHouse() {
  5. System.out.println(“Decorating Concrete Wall House”);
  6. }
  7. @Override
  8. public void paintHouse() {
  9. System.out.println(“Painting Concrete Wall House”);
  10. }
  11. @Override
  12. public void constructDoors() {
  13. System.out.println(“Constructing Doors for Concrete Wall House”);
  14. }
  15. @Override
  16. public void constructWindows() {
  17. System.out.println(“Constructing Windows for Concrete Wall House”);
  18. }
  19. @Override
  20. public void constructWalls() {
  21. System.out.println(“Constructing Concrete Wall for my House”);
  22. }
  23. }

GlassWallHouse.java

  1. package com.howtodoinjava.designpattern.template;
  2. public class GlassWallHouse extends House {
  3. @Override
  4. public void decorateHouse() {
  5. System.out.println("Decorating Glass Wall House");
  6. }
  7. @Override
  8. public void paintHouse() {
  9. System.out.println("Painting Glass Wall House");
  10. }
  11. @Override
  12. public void constructDoors() {
  13. System.out.println("Constructing Doors for Glass Wall House");
  14. }
  15. @Override
  16. public void constructWindows() {
  17. System.out.println("Constructing Windows for Glass Wall House");
  18. }
  19. @Override
  20. public void constructWalls() {
  21. System.out.println("Constructing Glass Wall for my House");
  22. }
  23. }

演示

让我们尝试建造两种房屋。

  1. package com.howtodoinjava.designpattern.template;
  2. public class Demo {
  3. public static void main(String[] args) {
  4. System.out.println(“Going to build Concrete Wall House”);
  5. House house = new ConcreteWallHouse();
  6. house.buildhouse();
  7. System.out.println(“Concrete Wall House constructed successfully”);
  8. System.out.println(“********************”);
  9. System.out.println(“Going to build Glass Wall House”);
  10. house = new GlassWallHouse();
  11. house.buildhouse();
  12. System.out.println(“Glass Wall House constructed successfully”);
  13. }
  14. }

输出:

  1. Going to build Concrete Wall House
  2. Base has been constructed.
  3. Roof has been constructed.
  4. Constructing Concrete Wall for my House
  5. Constructing Windows for Concrete Wall House
  6. Constructing Doors for Concrete Wall House
  7. Painting Concrete Wall House
  8. Decorating Concrete Wall House
  9. Concrete Wall House constructed successfully
  10. ********************
  11. Going to build Glass Wall House
  12. Base has been constructed.
  13. Roof has been constructed.
  14. Constructing Glass Wall for my House
  15. Constructing Windows for Glass Wall House
  16. Constructing Doors for Glass Wall House
  17. Painting Glass Wall House
  18. Decorating Glass Wall House
  19. Glass Wall House constructed successfully

关键设计要点

  1. 将模板方法标记为最终的,以便实现类无法覆盖和更改步骤的顺序。
  2. 在基类中,使用默认实现实现所有方法,因此派生类无需定义它们。
  3. 标记所有必须抽象实现派生类的方法

模板方法模式的流行实现

这些是模板方法设计模式的几种流行的现有实现。

  • Java IOInputStreamOutputStreamReaderWriter的非抽象方法。
  • 一些抽象集合类的非抽象方法,例如AbstractListAbstractSetAbstractMap等。

总结

模板模式是一种非常简单的设计模式,用于定义和实现编程示例中的某些顺序算法步骤。 它有助于定义算法的框架,该框架不得在子类中被覆盖。

因此,展望未来,当您需要实现上述业务场景时,请考虑一下模板模式 – 它非常易于实现并且也非常易于维护。

学习愉快!

下载源码