模板方法模式

<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
     }
 }
```