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:但我仍然在做大部分的工作