В объектно-ориентированном программировании метод шаблонов является одним из шаблонов поведенческого проектирования , выявленных Гаммой и др. [1] в книге « Шаблоны проектирования» . Метод шаблона — это метод суперкласса, обычно абстрактного суперкласса, который определяет скелет операции в виде ряда шагов высокого уровня. Эти шаги сами по себе реализуются дополнительными вспомогательными методами в том же классе, что и метод шаблона .
Вспомогательные методы могут быть либо абстрактными методами (в этом случае для предоставления конкретных реализаций требуются подклассы), либо методами-перехватчиками, которые имеют пустые тела в суперклассе. Подклассы могут (но не обязаны) настраивать операцию, переопределяя методы-перехватчики. Цель метода шаблона — определить общую структуру операции, позволяя при этом подклассам уточнять или переопределять определенные шаги. [2]
Этот шаблон состоит из двух основных частей:
Во время выполнения алгоритм, представленный методом шаблона, выполняется путем отправки сообщения шаблона экземпляру одного из конкретных подклассов. Благодаря наследованию начинает выполняться метод шаблона в базовом классе. Когда метод шаблона отправляет сообщение самому себе, запрашивая один из вспомогательных методов, сообщение будет получено конкретным подэкземпляром. Если вспомогательный метод был переопределен, будет выполнена переопределяющая реализация в подэкземпляре; если оно не было переопределено, будет выполнена унаследованная реализация в базовом классе. Этот механизм гарантирует, что весь алгоритм каждый раз выполняет одни и те же шаги, в то же время позволяя деталям некоторых шагов зависеть от того, какой экземпляр получил исходный запрос на выполнение алгоритма.
Этот шаблон является примером инверсии управления, поскольку код высокого уровня больше не определяет, какие алгоритмы запускать; вместо этого во время выполнения выбирается алгоритм более низкого уровня.
Некоторые из собственных сообщений, отправляемых методом шаблона, могут быть перехватчиками методов. Эти методы реализованы в том же базовом классе, что и метод шаблона, но с пустыми телами (т. е. они ничего не делают). Методы-перехватчики существуют для того, чтобы подклассы могли их переопределять и, таким образом, точно настраивать действие алгоритма без необходимости переопределять сам метод шаблона. Другими словами, они предоставляют «крючок», на который можно «подвесить» варианты реализации.
На приведенной выше диаграмме классов UML определяется операция , которая определяет скелет (шаблон) поведения с помощьюAbstractClass
templateMethod()
primitive1()
и primitive2()
, которые, поскольку они реализованы в SubClass1
, позволяют этому подклассу предоставлять вариант реализации этих частей алгоритма.Метод шаблона используется в средах, каждая из которых реализует инвариантные части архитектуры предметной области, предоставляя при этом методы-перехватчики для настройки. Это пример инверсии управления . Шаблонный метод используется по следующим причинам. [3]
Шаблон шаблона полезен при работе с автоматически сгенерированным кодом. Проблема работы со сгенерированным кодом заключается в том, что изменения в исходном коде приведут к изменениям в сгенерированном коде; если в сгенерированный код были внесены рукописные изменения, они будут потеряны. Как же тогда следует кастомизировать сгенерированный код?
Шаблон «Шаблон» предлагает решение. Если сгенерированный код соответствует шаблону шаблонного метода, весь сгенерированный код будет абстрактным суперклассом. При условии, что написанные вручную настройки ограничены подклассом, генератор кода можно запустить снова без риска перезаписи этих изменений. При использовании с генерацией кода этот шаблон иногда называют шаблоном разрыва поколений . [7]
Эта реализация C++14 основана на реализации до C++98, описанной в книге.
#include <iostream> #include <память> class View { // AbstractClass public : // определяет абстрактные примитивные операции, которые конкретные подклассы определяют для реализации шагов алгоритма. virtual void doDisplay () {} // реализует шаблонный метод, определяющий скелет алгоритма. Метод шаблона вызывает примитивные операции, а также операции, определенные в AbstractClass или других объектах. недействительный дисплей () { setFocus (); сделатьДисплей (); сброс фокуса (); } виртуальный ~ Просмотр () = по умолчанию ; Private : void setFocus () { std :: cout << "View::setFocus \n " ; } void resetFocus () { std :: cout << "View::resetFocus \n " ; } }; class MyView : public View { // ConcreteClass // реализует примитивные операции для выполнения шагов алгоритма, специфичных для подкласса. void doDisplay () override { // отображаем содержимое представления std :: cout << "MyView::doDisplay \n " ; } }; int main () { // Интеллектуальные указатели предотвращают утечки памяти std :: unique_ptr < View > myview = std :: make_unique < MyView > (); myview -> дисплей (); }
Вывод программы
View :: setFocus MyView :: doDisplay View :: resetFocus
Шаблонный метод широко используется в фреймворках.