class AbstractClass {
public:
    virtual void step1() = 0;
    virtual void step2() = 0;
    virtual void step3() = 0;
};
class ConcreteClass1 : public AbstractClass {
public:
    void step1() override {
        // 具體實現
    }
    void step2() override {
        // 具體實現
    }
    void step3() override {
        // 具體實現
    }
};
class ConcreteClass2 : public AbstractClass {
public:
    void step1() override {
        // 具體實現2
    }
    void step2() override {
        // 具體實現2
    }
    void step3() override {
        // 具體實現2
    }
};
class AbstractClass {
public:
    virtual void hook() {
        // 預設實現(可為空)
    }
};
class ConcreteClass : public AbstractClass {
public:
    void hook() override {
        // 客製化實現
    }
};
/**
 * 抽象類定義了一個模板方法,該方法包含某種算法的骨架,
 * 由對(通常是)抽象基本操作的呼叫組成。
 * 
 * 具體子類應實現這些操作,但保持模板方法本身不變。
 */
class AbstractClass {
  /**
   * 模板方法定義算法的骨架。
   */
 public:
  void TemplateMethod() const {
    this->BaseOperation1();
    this->RequiredOperations1();
    this->BaseOperation2();
    this->Hook1();
    this->RequiredOperation2();
    this->BaseOperation3();
    this->Hook2();
  }
  /**
   * 這些操作已經有實現。
   */
 protected:
  void BaseOperation1() const {
    std::cout << "AbstractClass:我正在做大部分的工作\n";
  }
  void BaseOperation2() const {
    std::cout << "AbstractClass:但我允許子類覆寫一些操作\n";
  }
  void BaseOperation3() const {
    std::cout << "AbstractClass:但我仍然在做大部分的工作\n";
  }
  /**
   * 這些操作必須在子類中實現
   */
  virtual void RequiredOperations1() const = 0;
  virtual void RequiredOperation2() const = 0;
  /**
   * 這些是"Hook"。子類可能覆寫它們,但這不是必須的,
   * 因為Hook已經有預設(但空的)實現。鉤子在算法的一些關鍵位置提供額外的擴展點。
   */
  virtual void Hook1() const {}
  virtual void Hook2() const {}
};
/**
 * 具體類必須實現基類的所有抽象操作
 * 它們也可以覆寫具有預設實現的一些操作
 */
class ConcreteClass1 : public AbstractClass {
 protected:
  void RequiredOperations1() const override {
    std::cout << "ConcreteClass1:實現Operation1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "ConcreteClass1:實現Operation2\n";
  }
};
/**
 * 通常,具體類只覆寫基類操作的一部分
 */
class ConcreteClass2 : public AbstractClass {
 protected:
  void RequiredOperations1() const override {
    std::cout << "ConcreteClass2:實現Operation1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "ConcreteClass2:實現Operation2\n";
  }
  void Hook1() const override {
    std::cout << "ConcreteClass2:覆寫Hook1\n";
  }
};
/**
 * 客戶端代碼調用模板方法以執行算法。客戶端代碼不必知道它所使用的對象的具體類
 * 只要它通過基類的接口與對象交互即可
 */
void ClientCode(AbstractClass *class_) {
  // ...
  class_->TemplateMethod();
  // ...
}
int main() {
  std::cout << "同一客戶端代碼可以與不同的子類一起工作:\n";
  ConcreteClass1 *concreteClass1 = new ConcreteClass1;
  ClientCode(concreteClass1);
  std::cout << "\n";
  
  std::cout << "同一客戶端代碼可以與不同的子類一起工作:\n";
  ConcreteClass2 *concreteClass2 = new ConcreteClass2;
  ClientCode(concreteClass2);
}
Output:
// ConcreteClass1
同一客戶端代碼可以與不同的子類一起工作:
AbstractClass:我正在做大部分的工作
ConcreteClass1:實現Operation1
AbstractClass:但我允許子類覆寫一些操作
ConcreteClass1:實現Operation2
AbstractClass:但我仍然在做大部分的工作
// ConcreteClass2
同一客戶端代碼可以與不同的子類一起工作:
AbstractClass:我正在做大部分的工作
ConcreteClass2:實現Operation1
AbstractClass:但我允許子類覆寫一些操作
ConcreteClass2:覆寫Hook1
ConcreteClass2:實現Operation2
AbstractClass:但我仍然在做大部分的工作