Implementing the Template Method Pattern in Java – 在Java中实现模板方法模式

最后修改: 2017年 11月 28日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll see how to leverage the template method pattern – one of the most popular GoF patterns.

在这个快速教程中,我们将看到如何利用模板方法模式 – 最受欢迎的GoF模式之一。

It makes it easier to implement complex algorithms by encapsulating logic in a single method.

它通过将逻辑封装在一个方法中,使复杂的算法更容易实现。

2. Implementation

2.实施

To demonstrate how the template method pattern works, let’s create a simple example which represents building a computer station.

为了证明模板方法模式是如何工作的,让我们创建一个简单的例子,它代表了建立一个计算机站。

Given the pattern’s definition, the algorithm’s structure will be defined in a base class that defines the template build() method:

考虑到模式的定义,算法的结构将在一个定义了模板build()方法的基类中定义

public abstract class ComputerBuilder {
    
    // ...
    
    public final Computer buildComputer() {
        addMotherboard();
        setupMotherboard();
        addProcessor();
        return new Computer(computerParts);
    }
   
    public abstract void addMotherboard();
    public abstract void setupMotherboard();
    public abstract void addProcessor();
    
    // ...
}

The ComputerBuilder class is responsible for outlining the steps required to build a computer by declaring methods for adding and setting up different components, such as a motherboard and a processor.

ComputerBuilder类负责通过声明添加和设置不同组件的方法来概述构建一台计算机所需的步骤,例如主板和处理器。

Here, the build() method is the template method, which defines steps of the algorithm for assembling the computer parts and returns fully-initialized Computer instances.

这里,build()方法是模板方法,它定义了组装计算机部件的算法步骤并返回完全初始化的计算机实例。

Notice that it’s declared as final to prevent it from being overridden.

注意,i它被声明为final,以防止它被重写。

3. In Action

3.在行动中

With the base class already set, let’s try to use it by creating two subclasses. One which builds a “standard” computer, and the other that builds a “high-end” computer:

在基类已经设置好的情况下,让我们试着通过创建两个子类来使用它。一个是建立一个 “标准 “计算机,另一个是建立一个 “高端 “计算机。

public class StandardComputerBuilder extends ComputerBuilder {

    @Override
    public void addMotherboard() {
        computerParts.put("Motherboard", "Standard Motherboard");
    }
    
    @Override
    public void setupMotherboard() {
        motherboardSetupStatus.add(
          "Screwing the standard motherboard to the case.");
        motherboardSetupStatus.add(
          "Pluging in the power supply connectors.");
        motherboardSetupStatus.forEach(
          step -> System.out.println(step));
    }
    
    @Override
    public void addProcessor() {
        computerParts.put("Processor", "Standard Processor");
    }
}

And here’s the HighEndComputerBuilder variant:

这里是HighEndComputerBuilder的变体。

public class HighEndComputerBuilder extends ComputerBuilder {

    @Override
    public void addMotherboard() {
        computerParts.put("Motherboard", "High-end Motherboard");
    }
    
    @Override
    public void setupMotherboard() {
        motherboardSetupStatus.add(
          "Screwing the high-end motherboard to the case.");
        motherboardSetupStatus.add(
          "Pluging in the power supply connectors.");
        motherboardSetupStatus.forEach(
          step -> System.out.println(step));
    }
    
    @Override
    public void addProcessor() {
         computerParts.put("Processor", "High-end Processor");
    }
}

As we can see, we didn’t need to worry about the whole assembly process but only for providing implementations for separate methods.

正如我们所看到的,我们不需要担心整个组装过程,只需要为不同的方法提供实现。

Now, let’s see it in action:

现在,让我们看看它的行动。

new StandardComputerBuilder()
  .buildComputer();
  .getComputerParts()
  .forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));
        
new HighEndComputerBuilder()
  .buildComputer();
  .getComputerParts()
  .forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));

4. Template Methods in Java Core Libraries

4.Java核心库中的模板方法

This pattern is widely used in the Java core libraries, for example by java.util.AbstractList, or java.util.AbstractSet.

这种模式在Java核心库中被广泛使用,例如,java.util.AbstractList,或java.util.AbstractSet.

For instance, Abstract List provides a skeletal implementation of the List interface.

例如,Abstract List 提供了List接口的一个骨架性实现。

An example of a template method can be the addAll() method, although it’s not explicitly defined as final:

模板方法的一个例子可以是addAll()方法,尽管它没有被明确定义为final:

public boolean addAll(int index, Collection<? extends E> c) {
    rangeCheckForAdd(index);
    boolean modified = false;
    for (E e : c) {
        add(index++, e);
        modified = true;
    }
    return modified;
}

Users only need to implement the add() method:

用户只需要实现add()方法。

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

Here, it’s the responsibility of the programmer to provide an implementation for adding an element to the list at the given index (the variant part of the listing algorithm).

在这里,程序员的责任是提供一个实现,在给定的索引处向列表添加一个元素(列表算法的变体部分)。

5. Conclusion

5.结论

In this article, we showed the template method pattern and how to implement it in Java.

在这篇文章中,我们展示了模板方法模式以及如何在Java中实现它。

The template method pattern promotes code reuse and decoupling, but at the expense of using inheritance.

模板方法模式促进了代码的重用和解耦,但以使用继承为代价。

As always, all the code samples shown in this article are available over on GitHub.

一如既往,本文中所展示的所有代码样本都可以在GitHub上找到