|
Программирование >> Разработка устойчивых систем
Стратегия Шаблонный метод содержит постоянный код , а переопределяемые функции содержат переменный код . Тем не менее, механизм наследования фиксирует эти изменения на стадии компиляции. Следуя принципу композиция предпочтительнее наследования , можно воспользоваться композицией для отделения изменяющегося кода от постоянного; так мы приходим к идее паттерна Стратегия (Strategy). Очевидным преимуществом такого подхода является возможность под- ций адаптирует приложение для конкретной ситуации. Шаблонный метод (Template method) принадлежит к числу важнейших концепций в прикладных библиотеках; обычно он остается скрытым от пользователя и управляет работой приложения посредством вызова различных функций базового класса (часть из которых была переопределена программистом при создании приложения). Важнейшая особенность Шаблонного метода заключается в том, что он определяется в базовом классе (иногда в виде закрытой функции) и не может изменяться. Он вызывает другие функции базовых классов для достижения своих целей, но прикладной программист не всегда может вызывать его напрямую, как показывает следующий пример: : СЮ:TempiateMethod.срр Простая демонстрация Шаблонного метода. linclude <iostream> using namespace std: class ApplicationFramework { protected: virtual void customizelO = 0: virtual void customize2() = 0: public: void tempiateMethodO { forCint i = 0: i < 5: i++) { customizelO: customize2(): Создание нового приложения : class МуАрр : public ApplicationFramework { protected: void customizelO { cout Hello : } void customize2() { cout World! endl: } int mainO { MyApp app: app.templateMethodO: } III:- Шаблонный метод - двигатель , обеспечивающий выполнение приложения. В графических приложениях таким двигателем обычно является основной цикл обработки событий. Прикладной программист просто предоставляет определения customizelO и customize2(), и приложение готово к работе. ключения переменного кода во время выполнения. Наряду со Стратегией добавляется паттерн Контекст (Context), то есть суррогатный класс, управляющий выбором и использованием конкретного объекта стратегии - совсем как Состояние! Термин стратегия означает лищь то, что у проблемы имеется несколько решений. Допустим, вы забыли, как зовут встреченного вами знакомого. Из неловкого положения можно выйти несколькими способами: : СЮ:Strategy.срр Паттерн Стратегия, linclude <iostreani> using namespace std: class NameStrategy { public: virtual void greet О = 0: class SayHi : public NameStrategy { public: void greet О { cout Hi! Hows it going? endl: class Ignore : public NameStrategy { public: void greetO { cout (Pretend I dont see you) endl: class Admission : public NameStrategy { public: void greetO { cout Im sorry. I forgot your name. endl: Контекст управляет выбором стратегии: class Context { NameStrategy& strategy: public: Context(NameStrategy& strat) : strategy(strat) {} void greetO { strategy.greetO: } int mainO { SayHi sayhi: Ignore ignore: Admission admission: Context cKsayhi), c2(ignore). c3(admission): cl.greetO: c2.greetО c3.greetО } /:- Метод Context::greet() обычно имеет более сложную структуру; как и шаблонный метод, он содержит неизменяемый код. Но функция main() наглядно показы- вает, что выбор стратегии может осуществляться на стадии выполнения программы. Можно пойти еще дальще, объединить этот паттерн с Состоянием и изменять Стратегию в течение жизненного цикла объекта Context. Цепочка ответственности Паттерн Цепочка ответственности (Chain of responsibility) может рассматриваться как динамическое обобщение рекурсии с использованием объектов Стратегии. Программа выдает вызов, и каждая стратегия в связанном списке пытается обслужить этот вызов. Процесс кончается тогда, когда одна из стратегий окажется успешной, или с завершением цепочки. При рекурсии одна функция многократно вызывает сама себя до тех пор, пока не будет достигнуто условие выхода; в Цепочке ответственности функция вызывает себя, что (в результате смещения по цепочке) приводит к вызову другой реализации этой функции, и т. д. вплоть до достижения выходного условия. Выходным условием является либо успешность одной из Стратегий, либо достижение конца цепочки. В последнем случае обычно возвращается объект по умолчанию; впрочем, не всегда, и тогда нужно предусмотреть другие возможности для проверки успеха или неудачи. Вместо того чтобы обслуживать запрос одной функцией, мы даем возможность обслужить запрос всем функциям цепочки. Такая процедура имеет нечто общее с экспертной системой. Поскольку цепочка фактически представляет собой список, она может создаваться динамически, так что ее можно рассматривать как обобщенную динамически создаваемую команду switch. В книге БЧ тема построения Цепочки ответственности в виде связанного списка обсуждается достаточно подробно. Однако с точки зрения паттерна способ построения цепочки уходит на второй план; он относится к подробностям реализации. Поскольку книга БЧ была написана до того, как контейнеры STL стали доступными в большинстве компиляторов С++, вероятно, такое внимание к техническим деталям объясняется следующими причинами: во-первых, в языке отсутствовали связанные списки, и реализация паттерна требовала создания их собственной версии; во-вторых, академическая наука относится к структурам данных как к одной из основополагающих дисциплин, и авторам БЧ просто не пришло в голову, что структуры данных могут быть включены в стандартный инструментарий языка программирования. Мы считаем, что самостоятельная реализация Цепочки ответственности в виде списка (по БЧ - связанного списка) ничего не добавляет к решению, и задача, как показано далее, также легко решается с применением контейнеров STL. В следующем примере Цепочка ответственности автоматически находит решение, используя механизм автоматического рекурсивного перебора всех Стратегий: : ClO:Cha1nOfReponsibility.cpp Подход пятилетнего ребенка, linclude <1ostream> linclude <vector> linclude ../purge.h using namespace std: enum Answer { NO, YES }: class GimmeStrategy {
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |