Паттерны » Паттерны поведения » Template Method
Паттерн Template Method (шаблонный метод)
Назначение паттерна Template Method
- Паттерн Template Method определяет основу алгоритма и позволяет подклассам изменить некоторые шаги этого алгоритма без изменения его общей структуры.
- Базовый класс определяет шаги алгоритма с помощью абстрактных операций, а производные классы их реализуют.
Решаемая проблема
Имеются два разных, но в тоже время очень похожих компонента. Вы хотите внести изменения в оба компонента, избежав дублирования кода.
Обсуждение паттерна Template Method
Проектировщик компонента решает, какие шаги алгоритма являются неизменными (или стандартными), а какие изменяемыми (или настраиваемыми). Абстрактный базовый класс реализует стандартные шаги алгоритма и может предоставлять (или нет) реализацию по умолчанию для настраиваемых шагов. Изменяемые шаги могут (или должны) предоставляться клиентом компонента в конкретных производных классах.
Проектировщик компонента определяет необходимые шаги алгоритма, порядок их выполнения, но позволяет клиентам компонента расширять или замещать некоторые из этих шагов.
Паттерн Template Method широко применяется в каркасах приложений (frameworks). Каждый каркас реализует неизменные части архитектуры в предметной области, а также определяет те части, которые могут или должны настраиваться клиентом. Таким образом, каркас приложения становится "центром вселенной", а настройки клиента являются просто "третьей планетой от Солнца". Эту инвертированную структуру кода ласково называют принципом Голливуда - "Не звоните нам, мы сами вам позвоним".
Структура паттерна Template Method
UML-диаграмма классов паттерна Template Method
Реализация метода templateMethod()
вызывает методы stepOne()
, stepTwo()
и stepThree()
. Метод stepTwo()
является "замещающим" методом. Он объявлен в базовом классе, а определяется в производных классах. Каркасы приложений широко используют паттерн Тemplate Method. Весь повторно используемый код определяется в базовых классах каркаса, нужное поведение системы клиенты определяют в создаваемых производных классах.
Пример паттерна Template Method
Паттерн Template Method определяет основу алгоритма и позволяет подклассам изменить некоторые шаги этого алгоритма без изменения его общей структуры. Строители зданий используют шаблонный метод при проектировании новых домов. Здесь могут использоваться уже существующие типовые планы, в которых модифицируются только отдельные части.
Использование паттерна Template Method
- Исследуйте алгоритм и решите, какие шаги являются стандартными, а какие должны определяться подклассами.
- Создайте новый абстрактный базовый класс, в котором будет реализован принцип "не звоните нам, мы сами вам позвоним".
- Поместите в новый класс основу алгоритма (шаблонный метод) и определения стандартных шагов.
- Для каждого шага, требующего различные реализации, определите "замещающий" виртуальный метод. Этот метод может иметь реализацию по умолчанию или быть чисто виртуальным.
- Вызовите "замещающий" метод из шаблонного метода.
- Создайте подклассы от нового абстрактного базового класса и реализуйте в них "замещающие" методы.
Особенности паттерна Template Method
- Template Method использует наследование для модификации части алгоритма. Стратегия использует делегирование для модификации всего алгоритма.
- Стратегия изменяет логику отдельных объектов. Template Method изменяет логику всего класса.
- Фабричные методы часто вызываются из шаблонных методов.
Реализация паттерна Template Method
- Стандартизуйте основу алгоритма в шаблонном методе базового класса.
- Для шагов, требующих особенной реализации, определите "замещающие" методы.
- Производные классы реализуют "замещающие" методы.
#include <iostream> using namespace std; class Base { void a() { cout << "a "; } void c() { cout << "c "; } void e() { cout << "e "; } // 2. Для шагов, требующих особенной реализации, определите // "замещающие" методы. virtual void ph1() = 0; virtual void ph2() = 0; public: // 1. Стандартизуйте основу алгоритма в шаблонном методе // базового класса void execute() { a(); ph1(); c(); ph2(); e(); } }; class One: public Base { // 3. Производные классы реализуют "замещающие" методы. /*virtual*/void ph1() { cout << "b "; } /*virtual*/void ph2() { cout << "d "; } }; class Two: public Base { /*virtual*/void ph1() { cout << "2 "; } /*virtual*/void ph2() { cout << "4 "; } }; int main() { Base *array[] = { &One(), &Two() }; for (int i = 0; i < 2; i++) { array[i]->execute(); cout << '\n'; } }
Вывод программы:
a b c d e a 2 c 4 e
Источник: http://sourcemaking.com/design_patterns/template_method/