stringtranslate.com

Схема цепочки ответственности

В объектно-ориентированном проектировании шаблон цепочки ответственности представляет собой шаблон поведенческого проектирования , состоящий из источника командных объектов и ряда объектов обработки . [1] Каждый объект обработки содержит логику, определяющую типы командных объектов, которые он может обрабатывать; остальные передаются следующему объекту обработки в цепочке. Также существует механизм добавления новых объектов обработки в конец этой цепочки.

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

Этот шаблон продвигает идею слабой связи .

Шаблон цепочки ответственности структурно почти идентичен шаблону декоратора , с той разницей, что для декоратора запрос обрабатывают все классы, а для цепочки ответственности запрос обрабатывает ровно один из классов в цепочке. Это строгое определение концепции ответственности в книге GoF . Однако многие реализации (например, средства ведения журнала ниже, обработка событий пользовательского интерфейса или фильтры сервлетов в Java и т. д.) позволяют нескольким элементам цепочки брать на себя ответственность.

Обзор

Шаблон проектирования «Цепочка ответственности» [2] — один из двадцати трех известных шаблонов проектирования GoF , которые описывают общие решения повторяющихся проблем проектирования при разработке гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменять, тестировать и повторно использовать.

Какие проблемы может решить шаблон проектирования «Цепочка ответственности»?

[3]

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

Какое решение описывает шаблон проектирования «Цепочка ответственности»?

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

См. также класс UML и диаграмму последовательности ниже.

Состав

Класс UML и диаграмма последовательности

Пример класса UML и диаграммы последовательности для шаблона проектирования «Цепочка ответственности». [4]

На приведенной выше диаграмме классов UML класс не ссылается напрямую на конкретный класс получателя. Вместо этого относится к интерфейсу обработки запроса ( ), что делает независимость от того, какой получатель обрабатывает запрос. Классы , и реализуют интерфейс путем обработки или пересылки запроса (в зависимости от условий времени выполнения). Диаграмма последовательности UML показывает взаимодействия во время выполнения: В этом примере объект вызывает объект (типа ). Перенаправляет запрос на , который, в свою очередь, перенаправляет запрос на , который обрабатывает (выполняет) запрос.SenderSenderHandlerhandler.handleRequest()SenderReceiver1Receiver2Receiver3Handler
SenderhandleRequest()receiver1Handlerreceiver1receiver2receiver3

Пример

Эта реализация C++11 основана на реализации до C++98, описанной в книге. [5]

#include <iostream> #include <память>  typedef int Тема ; constexpr Тема NO_HELP_TOPIC = -1 ;      // определяет интерфейс для обработки запросов. class HelpHandler { // Обработчик public : HelpHandler ( HelpHandler * h = nullptr , Topic t = NO_HELP_TOPIC ) : преемник ( h ), тема ( t ) {} virtual bool hasHelp () { return theme != NO_HELP_TOPIC ; } virtual void setHandler ( HelpHandler * , Topic ) {} virtual void handleHelp () { std :: cout << "HelpHandler::handleHelp \n " ; // (необязательно) реализует ссылку-преемник. if ( преемник != nullptr ) { преемник -> handleHelp (); } } виртуальный ~ HelpHandler () = по умолчанию ; HelpHandler ( const HelpHandler & ) = удалить ; // правило трех HelpHandler & оператор = ( const HelpHandler & ) = delete ; частный : HelpHandler * преемник ; Тема темы ; };                                                               класс Widget : public HelpHandler { public : Widget ( const Widget & ) = delete ; // правило трех Widget & оператор = ( const Widget & ) = delete ; защищенный : Виджет ( Виджет * w , Тема t = NO_HELP_TOPIC ) : HelpHandler ( w , t ), родитель ( nullptr ) { parent = w ; } Частное : Виджет * родительский ; };                                 // обрабатывает запросы, за которые отвечает. class Button : public Widget { // ConcreteHandler public : Button ( std :: shared_ptr < Widget > h , Topic t = NO_HELP_TOPIC ) : Widget ( h . get (), t ) {} virtual void handleHelp () { // если ConcreteHandler может обработать запрос, он это делает; в противном случае он пересылает запрос своему преемнику. std :: cout << "Button::handleHelp \n " ; if ( hasHelp ()) { // обрабатывает запросы, за которые он отвечает. } else { // может получить доступ к своему преемнику. HelpHandler :: handleHelp (); } } };                                    class Dialog : public Widget { // ConcreteHandler public : Dialog ( std :: shared_ptr < HelpHandler > h , Topic t = NO_HELP_TOPIC ) : Widget ( nullptr ) { setHandler ( h.get ( )), t ) ; } virtual void handleHelp () { std :: cout << "Dialog::handleHelp \n " ; // Операции виджета, которые Dialog переопределяет... if ( hasHelp ()) { // предлагает справку по диалогу } else { HelpHandler :: handleHelp (); } } };                                   class Application : public HelpHandler { public : Application ( Topic t ) : HelpHandler ( nullptr , t ) {} virtual void handleHelp () { std :: cout << "Application::handleHelp \n " ; // показываем список разделов справки } };                    int main () { constexpr Topic PRINT_TOPIC = 1 ; constexpr Тема PAPER_ORIENTATION_TOPIC = 2 ; constexpr Тема APPLICATION_TOPIC = 3 ; // Интеллектуальные указатели предотвращают утечки памяти. std :: shared_ptr < Приложение > application = std :: make_shared < Приложение > ( APPLICATION_TOPIC ); std :: shared_ptr < Диалог > диалог = std :: make_shared < Диалог > ( приложение , PRINT_TOPIC ); std :: shared_ptr < Кнопка > button = std :: make_shared < Кнопка > ( диалоговое окно , PAPER_ORIENTATION_TOPIC );                                 кнопка -> handleHelp (); }

Вывод программы:

Кнопка :: handleHelp

Реализации

Какао и какао-прикосновение

Платформы Cocoa и Cocoa Touch , используемые для приложений OS X и iOS соответственно, активно используют шаблон цепочки ответственности для обработки событий. Объекты, участвующие в цепочке, называются объектами -ответчиками и наследуются от класса NSResponder(OS X)/ UIResponder(iOS). Все объекты представления ( NSView/ UIView), объекты контроллера представления ( NSViewController/ UIViewController), объекты окна ( NSWindow/ UIWindow) и объект приложения ( NSApplication/ UIApplication) являются объектами-ответчиками.

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

Смотрите также

Рекомендации

  1. ^ «Шаблон проектирования цепочки ответственности» . Архивировано из оригинала 27 февраля 2018 г. Проверено 8 ноября 2013 г.
  2. ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. стр. 223 и далее. ISBN 0-201-63361-2.{{cite book}}: CS1 maint: несколько имен: список авторов ( ссылка )
  3. ^ «Шаблон проектирования цепочки ответственности - проблема, решение и применимость» . w3sDesign.com . Проверено 12 августа 2017 г.
  4. ^ «Шаблон проектирования «Цепочка ответственности - Структура и сотрудничество»» . w3sDesign.com . Проверено 12 августа 2017 г.
  5. ^ Эрих Гамма (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. стр. 189 и далее. ISBN 0-201-63361-2.