Найти тему
using Dev

Цепочка ответсвенности C#

Оглавление

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

Цепочка ответственностей применяется в случаях, если:

  • существует более одного обработчика исходного запроса;
  • (или) обработчики сообщения определяются во время выполнения приложения;
  • (или) необходимо отправить сообщение без явного указания получателя.

Как можно понять из описания, использование данного шаблона приводит к организации обработчиков событий в виде древовидной структуры или последовательной цепи. При этом само сообщение передается от более низких (детализированных) слоев к более высоким (более абстрактным).

Рассмотрим в качестве примера событие "нажатие клавиши", когда в приложении открыто диалоговое окно. Сообщение будет передано самому контекстному обработчику, принадлежащего активному элементу управления. Далее, в случае необходимости, оно будет переслано к более абстрактным обработчикам, принадлежащим (в порядке очередности) диалогу, его родительскому окну, а затем приложению. И если ни один из них не отреагирует на это сообщение, то оно будет утеряно.

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

В результате применения шаблона:

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

Можно выделить следующих участников шаблона:

  1. Интерфейс обработчика (IHandler) – определяет общий интерфейс для взаимодействия с клиентами.
  2. Обработчик (Handler) – непосредственная реализация, которая обрабатывает запрос.
  3. Управляющий объект (Manager) – не обязательный участник, который используется для построения структуры обработчиков и управления ей.

Особенности реализации и применения шаблона

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

Стоит отметить, что обработка сообщения не означает обязательного отказа в передаче его следующему обработчику в цепочке.

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

Еще одним важным моментом является определение формата сообщения. Возможны варианты:

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

Реализация шаблона в общем виде

  • разрабатываем интерфейс обработчиков;
  • определяем схему построения цепочки или дерева обработчиков (от контекстных к абстрактным);
  • выбираем формат сообщений;
  • определяем точку или способ взаимодействия с клиентом;
  • клиент отправляет сообщения, которое игнорируется или обрабатывается получателями;

Пример реализации

В примере рассмотрим как разные уровни строительства дома возлагаются на разные профессии.

Создадим интерфейс IWorker.

-2

Создадим абстрактный класс рабочего, реализующий интерфейс.

-3

Создадим конкретного рабочего, начнем с Дизайнера, который создаст дизайн дома.

-4

По аналогии создадим других рабочих.

-5

Рассмотрим применение паттерна.

-6

Результат.

-7

Наука
7 млн интересуются