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

Материал из Вики ИТ мехмата ЮФУ
Версия от 11:38, 1 августа 2014; Admin (обсуждение | вклад) (Достоинства и недостатки)

Перейти к: навигация, поиск

К основной странице курса

Другое название

Назначение

Некий запрос должен быть обработан в цепочке взаимосвязанных объектов (список, дерево - движение от листьев к корню). Объект либо обрабатывает запрос, либо передвает по цепочке следующему объекту. Если ни один из объектов не обработал запрос, то может происходить какое-то действие.

Описание

Имеется цепочка объектов, каждый хранит ссылку на следующий объект (как правило, объект более верхнего уровня) Запрос перемещается по цепочке объектов вверх пока один из них не обработает этот запрос. У объекта, отправившего запрос на обработку, отсутствует информация о том, какой объект в цепочке обработает запрос.

Пример: докладная пишется непосредственному начальнику, он либо реагирует на нее, либо передает по иерархии вверх своему непосредственному начальнику и т.д.

Использование

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

Реализация

Диаграмма классов

ChainCommon.png

Участники

Пример

class MainApp
{
    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 };

        h1.HandleRequest(2);
        h1.HandleRequest(22);
        h1.HandleRequest(222);
    }
}

abstract class Handler
{
    protected Handler successor;

    public void SetSuccessor(Handler successor)
    {
        this.successor = successor;
    }

    public abstract void HandleRequest(int request);
}

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);
        }
    }
}

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);
        }
    }
}

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);
        }
    }
}

Достоинства и недостатки

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

Варианты