Программирование >>  Разработка устойчивых систем 

1 ... 154 155 156 [ 157 ] 158 159 160 ... 196


Стратегия

Шаблонный метод содержит постоянный код , а переопределяемые функции содержат переменный код . Тем не менее, механизм наследования фиксирует эти изменения на стадии компиляции. Следуя принципу композиция предпочтительнее наследования , можно воспользоваться композицией для отделения изменяющегося кода от постоянного; так мы приходим к идее паттерна Стратегия (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 {



1 ... 154 155 156 [ 157 ] 158 159 160 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика