模板方法模式

<image>

模板方法（template method），是一种行为型软件设计模式。这种设计模式是一种控制反转的实现方式。因为高层代码不再确定（控制）算法的处理流程。

## 概述

模板方法是一个定义在父类别的方法，负责处理流程、算法的不变部分。模板方法会调用多个定义在父类别的其他工具方法，而这些方法是算法的可变部分，有可能只是抽象方法并没有实作，或者是只有空体的钩子方法。模板方法仅决定这些抽象方法的执行顺序，这些抽象方法由子类别负责实作，并且子类别不允许覆盖模板方法（即不能重写处理流程）。

模板方法模式多用在：某些类别的算法中，实做了相同的方法，造成程式码的重复；控制子类别必须遵守的一些事项。

## 结构

<image>

在上面的UML类图中，`AbstractClass`定义一个模板方法`templateMethod()`运算，它定义了行为的骨干即模板：

- 实现行为的不变部分。
- 向自身发送消息`primitive1()`和`primitive2()`，由于它们实现于`SubClass1`，这允许了子类提供这个算法的这些部分的可变实现。

## 用例

### C++

下面是基于《设计模式》书中前C++98实现的C++23实现例子：

<image>

```c++
import std;

using std::unique_ptr;

// abstract class
class View {
private:
    void setFocus() {
        std::println("View::setFocus called");
    }

    void resetFocus() {
        std::println("View::resetFocus called");
    }
public:
    // defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm.
    virtual void doDisplay() = 0;

    // implements a template method defining the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects.
    void display() {
        setFocus();
        doDisplay();
        resetFocus();
    }

    virtual ~View() = default;
};

// concrete class
class MyView : public View {
public:
    // implements the primitive operations to carry out subclass-specific steps of the algorithm.
    void doDisplay() override {
        // render the view's contents
        std::println("MyView::doDisplay called");
    }
};

int main(int argc, char* argv[]) {
    unique_ptr<View> myview = std::make_unique<MyView>();
    myview->display();
}
```

这个程序的输出为：

```output
View::setFocus called
MyView::doDisplay called
View::resetFocus called
```

### Python

下面是Python的例子：

```python
from abc import ABC, abstractmethod

class View(ABC):
    @abstractmethod
    def do_display(self): pass
    def display(self):
        self.__set_focus()
        self.do_display()
        self.__reset_focus()
    def __set_focus(self):
        print("View: set focus")
    def __reset_focus(self):
        print("View: reset focus")

class MyView(View):
    def do_display(self):
        print("View: do display")
```

其执行：

```pycon
>>> view = MyView()
>>> view.display()
View: set focus
View: do display
View: reset focus
```

### Java

下面是Java的例子：

```java
 /**
  * An abstract class that is common to several games in
  * which players play against the others, but only one is
  * playing at a given time.
  */
 abstract class Game {
     private int playersCount;
     abstract void initializeGame();
     abstract void makePlay(int player);
     abstract boolean endOfGame();
     abstract void printWinner();
 
     /* A template method : */
     final void playOneGame(int playersCount) {
         this.playersCount = playersCount;
         initializeGame();
         int j = 0;
         while (!endOfGame()){
             makePlay(j);
             j = (j + 1) % playersCount;
         }
         printWinner();
     }
 }

//Now we can extend this class in order to implement actual games:
 class Chess extends Game {
     /* Implementation of necessary concrete methods */
     void initializeGame() {
         // ...
     }
 
     void makePlay(int player) {
         // ...
     }
 
     boolean endOfGame() {
         // ...
     }
 
     void printWinner() {
         // ...
     }
  
     /* Specific declarations for the chess game. */
     // ...
 }

 public class Player {
     public static void main(String[] args) {
         Game chessGame = new Chess();
         chessGame.initializeGame();
         chessGame.playOneGame(1); //call template method
     }
 }
```