- Цепочка обязанностей
-
Шаблон проектирования поведенческий Chain of responsibility Тип: поведенческий
Назначение: для организации в системе уровней ответственности
Родственные шаблоны: Описан в Design Patterns Да
Цепочка обязанностей — поведенческий шаблон проектирования, предназначенный для организации в системе уровней ответственности.
Содержание
Применение
Шаблон рекомендован для использования в условиях:
- в разрабатываемой системе имеется группа объектов, которые могут обрабатывать сообщения определенного типа;
- все сообщения должны быть обработаны хотя бы одним объектом системы;
- сообщения в системе обрабатываются по схеме «обработай сам либо перешли другому», то есть одни сообщения обрабатываются на том уровне, где они получены, а другие пересылаются объектам иного уровня.
Примеры
Пример на PHP5
Исходный текст на PHP5.3namespace ChainOfResponsibility { abstract class Logger { const ERR = 3; const NOTICE = 5; const DEBUG = 7; protected $mask; // The next element in the chain of responsibility protected $next; public function __construct($mask) { $this->mask = $mask; } public function setNext(Logger $log) { $this->next = $log; return $log; } public function message($msg, $priority) { if ($priority <= $this->mask) { $this->writeMessage($msg); } if ($this->next != null) { $this->next->message($msg, $priority); } } protected abstract function writeMessage($msg); } class StdoutLogger extends Logger { protected function writeMessage($msg) { echo sprintf("Writing to stdout: %s\n", $msg); } } class EmailLogger extends Logger { protected function writeMessage($msg) { echo sprintf("Sending via email: %s\n", $msg); } } class StderrLogger extends Logger { protected function writeMessage($msg) { echo sprintf("Sending to stderr: %s\n", $msg); } } //цепочка обязанностей class ChainOfResponsibilityExample { public function run() { // строим цепочку обязанностей $logger = new StdoutLogger(Logger::DEBUG); $logger1 = $logger->setNext(new EmailLogger(Logger::NOTICE)); $logger2 = $logger1->setNext(new StderrLogger(Logger::ERR)); // Handled by StdoutLogger and StdoutLogger $logger->message("Entering function y.", Logger::DEBUG); // Handled by StdoutLogger and EmailLogger $logger->message("Step1 completed.", Logger::NOTICE); // Handled by all three loggers $logger->message("An error has occurred.", Logger::ERR); } } $chain = new ChainOfResponsibilityExample(); $chain->run(); }
Пример на Java
Исходный текст на Javapackage chainofresp; abstract class Logger { public static int ERR = 3; public static int NOTICE = 5; public static int DEBUG = 7; protected int mask; // The next element in the chain of responsibility protected Logger next; public Logger setNext(Logger log) { next = log; return log; } public void message(String msg, int priority) { if (priority <= mask) { writeMessage(msg); } if (next != null) { next.message(msg, priority); } } abstract protected void writeMessage(String msg); } class StdoutLogger extends Logger { public StdoutLogger(int mask) { this.mask = mask; } protected void writeMessage(String msg) { System.out.println("Writing to stdout: " + msg); } } class EmailLogger extends Logger { public EmailLogger(int mask) { this.mask = mask; } protected void writeMessage(String msg) { System.out.println("Sending via email: " + msg); } } class StderrLogger extends Logger { public StderrLogger(int mask) { this.mask = mask; } protected void writeMessage(String msg) { System.err.println("Sending to stderr: " + msg); } } public class ChainOfResponsibilityExample { public static void main(String[] args) { // Build the chain of responsibility Logger logger, logger1,logger2; logger = new StdoutLogger(Logger.DEBUG); logger1 = logger.setNext(new EmailLogger(Logger.NOTICE)); logger2 = logger1.setNext(new StderrLogger(Logger.ERR)); // Handled by StdoutLogger logger.message("Entering function y.", Logger.DEBUG); // Handled by StdoutLogger and EmailLogger logger.message("Step1 completed.", Logger.NOTICE); // Handled by all three loggers logger.message("An error has occurred.", Logger.ERR); } } /* The output is: Writing to stdout: Entering function y. Writing to stdout: Step1 completed. Sending via e-mail: Step1 completed. Writing to stdout: An error has occurred. Sending via e-mail: An error has occurred. Writing to stderr: An error has occurred. */ [edit]
Пример на C#
Исходный текст на языке C#// Chain of Responsibility pattern -- Structural example using System; namespace DoFactory.GangOfFour.Chain.Structural { /// <summary> /// MainApp startup class for Structural /// Chain of Responsibility Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Setup Chain of Responsibility Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); // Generate and process request int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; foreach (int request in requests) { h1.HandleRequest(request); } // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Handler' abstract class /// </summary> abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } /// <summary> /// The 'ConcreteHandler1' class /// </summary> class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } /// <summary> /// The 'ConcreteHandler2' class /// </summary> class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } /// <summary> /// The 'ConcreteHandler3' class /// </summary> class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } } Output ConcreteHandler1 handled request 2 ConcreteHandler1 handled request 5 ConcreteHandler2 handled request 14 ConcreteHandler3 handled request 22 ConcreteHandler2 handled request 18 ConcreteHandler1 handled request 3 ConcreteHandler3 handled request 27 ConcreteHandler3 handled request 20
Пример на C++
Исходный текст на языке C++#include <iostream> class Colleague; class Mediator { public: virtual void Send(std::string message, Colleague *colleague)=0; virtual ~Mediator(){} }; class Colleague { protected: Mediator *mediator; public: Colleague(Mediator *mediator) { this->mediator=mediator; } virtual ~Colleague(){} }; class ConcreteColleague1:public Colleague { public: ConcreteColleague1(Mediator *mediator):Colleague(mediator) { } void Send(std::string message) { mediator->Send(message, this); } void Notify(std::string message) { std::cout << "Colleague1 gets message " << message.c_str() << std::endl; } }; class ConcreteColleague2:public Colleague { public: ConcreteColleague2(Mediator *mediator):Colleague(mediator) { } void Send(std::string message) { mediator->Send(message, this); } void Notify(std::string message) { std::cout << "Colleague2 gets message " << message.c_str() << std::endl; } }; class ConcreteMediator:public Mediator { protected: ConcreteColleague1 *m_Colleague1; ConcreteColleague2 *m_Colleague2; public: void SetColleague1(ConcreteColleague1 *c) { m_Colleague1=c; } void SetColleague2(ConcreteColleague2 *c) { m_Colleague2=c; } virtual void Send(std::string message, Colleague *colleague) { if (colleague==static_cast<Colleague*>(m_Colleague1)) { m_Colleague2->Notify(message); } else if (colleague==static_cast<Colleague*>(m_Colleague2)) { m_Colleague1->Notify(message); } } }; int main(int argc, char **argv) { ConcreteMediator *m = new ConcreteMediator(); ConcreteColleague1 *c1 = new ConcreteColleague1(m); ConcreteColleague2 *c2 = new ConcreteColleague2(m); m->SetColleague1(c1); m->SetColleague2(c2); c1->Send("How are you?"); c2->Send("Fine, thanks"); std::cin.get(); return 0; } Output Colleague2 gеts message How are you? Colleague1 gеts message Fine, thanks
Источники
Ссылки
- Паттерн Chain of Responsibility (цепочка обязанностей) — назначение, описание, особенности и реализация на С++.
Шаблоны проектирования Основные Порождающие Структурные Поведенческие Интерпретатор • Итератор • Команда • Наблюдатель • Посетитель • Посредник • Состояние • Стратегия • Хранитель • Цепочка обязанностей • Шаблонный метод
Блокировка с двойной проверкой • Однопоточное выполнение • Планировщик Категория:- Шаблоны проектирования
Wikimedia Foundation. 2010.