Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПИАПС / knigaVAPO_v2.doc
Скачиваний:
363
Добавлен:
17.04.2018
Размер:
35.96 Mб
Скачать

5.6. Паттерны поведения

Паттерны поведения связаны с алгоритмами и распределением обязанностей между объектами. Речь в них идет не только о самих объектах и классах, но и о типичных способах взаимодействия. Паттерны поведения характеризуют сложный поток управления, который трудно проследить во время выполнения программы. Внимание акцентировано не на потоке управления как таковом, а на связях между объектами.

В паттернах поведения уровня класса используется наследование для распределения поведение между разными классами. Шаблонный метод представляет собой абстрактное определение алгоритма. Алгоритм определяется пошагово. На каждом шаге вызывается либо примитивная, либо абстрактная операция. Алгоритм ≪обрастает мясом≫ за счет подклассов, где определены абстрактные операции. Интерпретатор представляет грамматику языка в виде иерархии классов и реализуется как последовательность операций над экземплярами этих классов.

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

Паттерн цепочка обязанностей позволяет и дальше уменьшать степень связанности. Он дает возможность посылать запросы объекту не напрямую, а по цепочке ≪объектов-кандидатов≫. Запрос может выполнить любой ≪кандидат≫, если это допустимо в текущем состоянии выполнения программы. Число кандидатов заранее не определено, а подбирать участников можно во время выполнения.

Паттерн наблюдатель определяет и отвечает за зависимости между объектами. Классический пример наблюдателя встречается в схеме модель/вид/контроллер, где все виды модели уведомляются о любых изменениях ее состояния.

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

5.6.1. ПаттернЦепочка обязанностей (Chain of Responsibility)

Название и классификация паттерна

Цепочка обязанностей - паттерн поведения объектов.

Назначение

  • Паттерн Chain of Responsibility позволяет избежать жесткой зависимости отправителя запроса от его получателя, при этом запрос может быть обработан несколькими объектами. Объекты-получатели связываются в цепочку. Запрос передается по этой цепочке, пока не будет обработан.

  • Вводит конвейерную обработку для запроса с множеством возможных обработчиков.

  • Объектно-ориентированный связанный список с рекурсивным обходом.

Решаемая проблема

Имеется поток запросов и переменное число "обработчиков" этих запросов. Запрос может быть обработан различными объектами, но заранее неизвестно какими и эти объекты должны быть найдены автоматически без явного указания набора объектов, способных обработать запрос.

Паттерн Цепочка обязанностей инкапсулирует элементы по обработке запросов внутри абстрактного "конвейера". Клиенты "кидают" свои запросы на вход этого конвейера.

Паттерн Цепочка обязанностей связывает в цепочку объекты-получатели, а затем передает запрос-сообщение от одного объекта к другому до тех пор, пока не достигнет объекта, способного его обработать. Число и типы объектов-обработчиков заранее неизвестны, они могут настраиваться динамически. Механизм связывания в цепочку использует рекурсивную композицию, что позволяет использовать неограниченное число обработчиков.

Паттерн Цепочка обязанностей упрощает взаимосвязи между объектами. Вместо хранения ссылок на всех кандидатов-получателей запроса, каждый отправитель хранит единственную ссылку на начало цепочки, а каждый получатель имеет единственную ссылку на своего преемника - последующий элемент в цепочке.

Структура паттерна Цепочка обязанностей

Производные классы знают, как обрабатывать запросы клиентов. Если "текущий" объект не может обработать запрос, то он делегирует его базовому классу, который делегирует "следующему" объекту и так далее.

UML-диаграмма классов паттерна Цепочка обязанностей

Участники

  • Handler - обработчик: определяет интерфейс для обработки запросов; (необязательно) реализует связь с преемником;

  • HandlerOne (HandlerTwo...) - конкретный обработчик: обрабатывает запрос, за который отвечает; имеет доступ к своему преемнику; если Handler способен обработать запрос, то так и делает, если не может, то направляет его - его своему преемнику;

  • Client - клиент: отправляет запрос некоторому объекту Handler в цепочке.

Отношения

Когда клиент инициирует запрос, он продвигается по цепочке, пока некоторый объект Handler не возьмет на себя ответственность за его обработку. Обработчики могут вносить свой вклад в обработку каждого запроса. Запрос может быть передан по всей длине цепочки до самого последнего звена.

Пример паттерна Цепочка обязанностей

Паттерн Chain of Responsibility позволяет избежать привязки отправителя запроса к его получателю, давая шанс обработать запрос нескольким получателям. Банкомат использует Chain of Responsibility в механизме выдачи денег.

Использование паттерна Цепочка обязанностей

  • Базовый класс имеет указатель на "следующий обработчик".

  • Каждый производный класс реализует свой вклад в обработку запроса.

  • Если запрос должен быть "передан дальше", то производный класс "вызывает" базовый класс, который с помощью указателя делегирует запрос далее.

  • Клиент (или третья сторона) создает цепочку получателей (которая может иметь ссылку с последнего узла на корневой узел).

  • Клиент передает каждый запрос в начало цепочки.

  • Рекурсивное делегирование создает иллюзию волшебства.

Особенности паттерна Chain of Responsibility

  • Паттерны Chain of Responsibility, Command, Mediator и Observer показывают, как можно разделить отправителей и получателей с учетом их особенностей. Chain of Responsibility передает запрос отправителя по цепочке потенциальных получателей.

  • Chain of Responsibility может использовать Command для представления запросов в виде объектов.

  • Chain of Responsibility часто применяется вместе с паттерном Composite. Родитель компонента может выступать в качестве его преемника.

Реализация паттерна Chain of Responsibility по шагам

  • Создайте указатель на следующий обработчик next в базовом классе.

  • Метод handle() базового класса всегда делегирует запрос следующему объекту.

  • Если производные классы не могут обработать запрос, они делегируют его базовому классу.

#include <iostream>

#include <vector>

#include <ctime>

using namespace std;

 

class Base

{

    // 1. Указатель "next" в базовом классе

    Base *next;

  public:

    Base()

    {

        next = 0;

    }

Соседние файлы в папке ПИАПС