Книга: Экстремальное программирование. Разработка через тестирование
Шаблонный метод (Template Method)
Шаблонный метод (Template Method)
Как можно запрограммировать инвариантную последовательность операций, обеспечив при этом возможность модификации или замены отдельных действий в будущем? Напишите реализацию метода исключительно в терминах других методов.
В программировании существует огромное количество классических последовательностей:
• ввод – обработка – вывод;
• отправить сообщение – принять ответ;
• прочитать команду – вернуть результат.
Нам хотелось бы четко и понятно обозначить универсальность этих последовательностей и при этом обеспечить возможность варьирования реализаций каждого из отдельных этапов.
Поддерживаемый любым объектно-ориентированным языком механизм наследования обеспечивает простой способ определения универсальных последовательностей. В суперклассе создается метод, целиком и полностью написанный в терминах других методов. Каждый из подклассов может реализовать эти методы так, как ему удобнее. Например, базовая последовательность выполнения теста определяется в инфраструктуре JUnit следующим образом:
TestCase
public void runBare() throws Throwable {
setUp();
try {
runTest();
}
finally {
tearDown();
}
}
Классы, производные от TestCase, могут реализовать setUp(), runTest() и tearDown() так, как им этого хочется.
При использовании шаблона «Шаблонный метод» (Template Method) возникает вопрос: надо ли создавать для подметодов реализации по умолчанию? В TestCase.runBare() все три подметода обладают реализациями по умолчанию:
• методы setUp() и tearDown() не выполняют никаких операций;
• метод runTest() динамически обнаруживает и запускает все тестовые методы, исходя из имени класса-теста.
Если общая последовательность не имеет смысла, когда не определен один из ее этапов, вы должны отметить это, воспользовавшись любой подходящей возможностью используемого вами языка программирования:
• в Java можно объявить подметод абстрактным;
• в Smalltalk создайте реализацию метода, которая генерирует ошибку SubclassResponsibility.
Я не рекомендую изначально проектировать код так, чтобы в нем использовался шаблонный метод. Лучше всего формировать шаблонные методы исходя из накопленного опыта. Каждый раз, когда я говорю себе: «Ага, вот последовательность, а вот – детали реализации», – позднее я всегда обнаруживаю, что мне приходится переделывать созданный мною шаблонный метод, заново перетасовывая код между общим и частным.
Если вы обнаружили два варианта последовательности в двух подклассах, вы должны попытаться постепенно приблизить их друг к другу. После того как вы отделите различающиеся части и выделите общую часть, то, что останется, и есть шаблонный метод. После этого вы можете переместить шаблонный метод в суперкласс и избавиться от дублирования.
- Команда (Command)
- Объект-значение (Value Object)
- Нуль-объект (Null Object)
- Шаблонный метод (Template Method)
- Встраиваемый объект (Pluggable Object)
- Встраиваемый переключатель (Pluggable Selector)[26]
- Фабричный метод (Factory Method)
- Самозванец (Imposter)
- Компоновщик (Composite)
- Накапливающий параметр (Collecting Parameter)
- Одиночка (Singleton)
- 15.4 Resource Synchronization Methods
- Using Fedora's kickstart Installation Method
- 6.1.5. Trial-and-Error Method
- 8.3. Driver Methods
- Methods of Attack
- Managing disk quota templates
- Using security templates
- Using the Security Templates and Security Configuration And Analysis snap-ins
- Reviewing and changing template settings
- Analyzing, reviewing, and applying security templates
- Deploying security templates to multiple computers
- Adding Additional Test Methods