Назначение: определяет основу алгоритма и позволяет подклассам переопределить некоторые шаги алгоритма, не изменяя его структуру в целом.

Задача. Рассмотрим каркас приложения, в котором имеются классы Application и Document. Класс Application отвечает за открытие существующих документов, хранящихся во внешнем формате, например в виде файла. Объект класса Document представляет информацию документа после его прочтения из файла. Приложения, построенные на базе этого каркаса, могут порождать подклассы от классов Application и Document, отвечающие конкретным потребностям. Например, графический редактор определит подклассы DrawApplication и DrawDocument, а электронная таблица – подклассы SpreadsheetApplication и SpreadsheetDocument.

Очевидно, что логика алгоритма открытия документов в любом приложении достаточно однотипна:

1) проверяется, можно ли в текущем состоянии приложения открыть документ;

2) производится выбор имени файла (например, предлагается пользователю сделать это в диалоговом окне);

3) проверяется сам факт существования указанного файла, корректность его формата;

4) выполняется специализированное для каждого приложения считывание внутренней информации файла и создается объект-документ;

5) документ добавляется к списку документов приложения.

Таким образом, возникает задача исключения избыточности алгоритмов операций создания документов в классах иерархии Application.

Решение. Паттерн Шаблонный Метод предлагает определить в абстрактном классе Application общий алгоритм открытия и считывания документа в виде операции OpenDocument. Программный код такой операции может выглядеть так:

if (CanOpenDocument())

{

string filename = SelectFileName();

if (FileExists(filename))

{

Document doc = LoadDocument(filename);

documents.Add(doc);

}

}

 

 

Операции, подобные OpenDocument, называют шаблонными методами. Они описывают алгоритм в терминах абстрактных операций, которые замещены в подклассах для получения нужного поведения. Подклассы класса Application самостоятельно определяют, как выполнить проверку возможности открытия (CanOpenDocument), как выбрать файл (SelectFileName), корректность выбранного файла (FileExists), а также сам процесс конструирования документа на основе информации из файла (LoadDocument).

Определяя некоторые шаги алгоритма с помощью абстрактных операций, шаблонный метод фиксирует их последовательность, но позволяет реализовать их в подклассах. При этом сохраняется общий ход алгоритма и конкретика некоторых шагов, которые неизменны для потомков.

Общая структура решения.

 

 

AbstractClass (Application) – абстрактный класс: определяет абстрактные примитивные операции, замещаемые в конкретных подклассах для реализации шагов алгоритма; реализует шаблонный метод TemplateMethod, определяющий скелет алгоритма. Шаблонный метод вызывает примитивные операции PrimitiveOperation, а также операции, определенные в классе AbstractClass или в других объектах.

ConcreteClass (DrawApplication) – конкретный класс: реализует примитивные операции, выполняющие шаги алгоритма способом, специфическим для данного подкласса.

ConcreteClass предполагает, что инвариантные шаги алгоритма будут выполнены в AbstractClass.

Применимость. Используйте паттерн Шаблонный Метод:

Результаты. Шаблонные методы – один из фундаментальных приемов повторного использования кода. Они особенно важны в библиотеках классов, поскольку предоставляют возможность вынести общее поведение в библиотечные классы.

Шаблонные методы приводят к инвертированной структуре кода, которую иногда называют принципом Голливуда, подразумевая часто употребляемую в этой киноимперии фразу «Не звоните нам, мы сами позвоним». В данном случае это означает, что родительский класс вызывает операции подкласса, а не как обычно – наоборот.

Особенности реализации:

Родственные паттерны.

Фабричные Методы часто вызываются из Шаблонных Методов (в примере шаблонный метод OpenDocument вызывал фабричный метод LoadDocument).

Стратегия: Шаблонные Методы применяют наследование для модификации части алгоритма. Стратегии используют делегирование для модификации алгоритма в целом.