Шаблонний метод — це поведінковий патерн, який визначає кістяк алгоритму в суперкласі та змушує підкласи реалізувати конкретні кроки цього алгоритму.
Складність:
Популярність:
Застосування: Шаблонні методи можна зустріти в багатьох бібліотечних класах C++. Розробники створюють їх, щоб дозволити клієнтам легко та швидко розширювати стандартний код за допомогою спадкування.
Ознаки застосування патерна: Клас змушує своїх нащадків реалізувати методи-кроки, але самостійно реалізовує структуру алгоритму.
Концептуальний приклад
Цей приклад показує структуру патерна Шаблонний метод , а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.
main.cc: Приклад структури патерна
/**
* The Abstract Class defines a template method that contains a skeleton of some
* algorithm, composed of calls to (usually) abstract primitive operations.
*
* Concrete subclasses should implement these operations, but leave the template
* method itself intact.
*/
class AbstractClass {
/**
* The template method defines the skeleton of an algorithm.
*/
public:
void TemplateMethod() const {
this->BaseOperation1();
this->RequiredOperations1();
this->BaseOperation2();
this->Hook1();
this->RequiredOperation2();
this->BaseOperation3();
this->Hook2();
}
/**
* These operations already have implementations.
*/
protected:
void BaseOperation1() const {
std::cout << "AbstractClass says: I am doing the bulk of the work\n";
}
void BaseOperation2() const {
std::cout << "AbstractClass says: But I let subclasses override some operations\n";
}
void BaseOperation3() const {
std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\n";
}
/**
* These operations have to be implemented in subclasses.
*/
virtual void RequiredOperations1() const = 0;
virtual void RequiredOperation2() const = 0;
/**
* These are "hooks." Subclasses may override them, but it's not mandatory
* since the hooks already have default (but empty) implementation. Hooks
* provide additional extension points in some crucial places of the
* algorithm.
*/
virtual void Hook1() const {}
virtual void Hook2() const {}
};
/**
* Concrete classes have to implement all abstract operations of the base class.
* They can also override some operations with a default implementation.
*/
class ConcreteClass1 : public AbstractClass {
protected:
void RequiredOperations1() const override {
std::cout << "ConcreteClass1 says: Implemented Operation1\n";
}
void RequiredOperation2() const override {
std::cout << "ConcreteClass1 says: Implemented Operation2\n";
}
};
/**
* Usually, concrete classes override only a fraction of base class' operations.
*/
class ConcreteClass2 : public AbstractClass {
protected:
void RequiredOperations1() const override {
std::cout << "ConcreteClass2 says: Implemented Operation1\n";
}
void RequiredOperation2() const override {
std::cout << "ConcreteClass2 says: Implemented Operation2\n";
}
void Hook1() const override {
std::cout << "ConcreteClass2 says: Overridden Hook1\n";
}
};
/**
* The client code calls the template method to execute the algorithm. Client
* code does not have to know the concrete class of an object it works with, as
* long as it works with objects through the interface of their base class.
*/
void ClientCode(AbstractClass *class_) {
// ...
class_->TemplateMethod();
// ...
}
int main() {
std::cout << "Same client code can work with different subclasses:\n";
ConcreteClass1 *concreteClass1 = new ConcreteClass1;
ClientCode(concreteClass1);
std::cout << "\n";
std::cout << "Same client code can work with different subclasses:\n";
ConcreteClass2 *concreteClass2 = new ConcreteClass2;
ClientCode(concreteClass2);
delete concreteClass1;
delete concreteClass2;
return 0;
}
Output.txt: Результат виконання
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Шаблонний метод іншими мовами програмування