模板方法模式

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

概述
模板方法是一個定義在父類別的方法，负责处理流程、算法的不变部分。模板方法會调用多個定義在父類別的其他工具方法，而這些方法是算法的可变部分，有可能只是抽象方法並沒有實作，或者是只有空体的钩子方法。模板方法僅決定這些抽象方法的執行順序，這些抽象方法由子類別負責實作，並且子類別不允許覆盖模板方法（即不能重写处理流程）。

模板方法模式多用在：某些類別的演算法中，實做了相同的方法，造成程式碼的重複；控制子類別必須遵守的一些事項。

 结构 

在上面的UML类图中，AbstractClass定义一个模板方法templateMethod()运算，它定义了行为的骨干即模板：
 实现行为的不变部份。
 向自身发送消息primitive1()和primitive2()，由于它们实现于SubClass1，这允许了子类提供这个算法的这些部份的可变实现。

用例
C++
下面是基于《设计模式》书中前C++98实现的C++23实现例子：
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();
}

这个程序的输出为：

View::setFocus called
MyView::doDisplay called
View::resetFocus called

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")
其执行：
>>> view = MyView()
>>> view.display()
View: set focus
View: do display
View: reset focus

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

引用

Category:软件设计模式