1 11.2K ru

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

Categories: 💻 Programming

Назначение:

Позволяет избежать привязки отправителя запроса к его получателю, давая шанс обработать запрос нескольким объектам. Связывает объекты-получатели в цепочку и передает запрос вдоль этой цепочки, пока его не обработают. «Цепочка обязанностей» является довольно распространенным паттерном в .NET Framework, хотя не все знают, что часто пользуются им. Цепочка обязанностей — это любое событие, аргументы которого позволяют уведомить инициатора, что событие обработано с помощью метода Handle() или путем установки свойства Handled в True.

Когда использовать Паттерн Chain of responsibility:

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

UML схема паттерна "Цепочка Обязанностей":

Chain of responsibility

Реализация шаблона "Цепочка Обязанностей" на C#:

class Program
{
    static void Main(string[] args)
    {
        Receiver receiver = new Receiver(false, true, true);
         
        PaymentHandler bankPaymentHandler = new BankPaymentHandler();
        PaymentHandler moneyPaymentHnadler = new MoneyPaymentHandler();
        PaymentHandler paypalPaymentHandler = new PayPalPaymentHandler();
        bankPaymentHandler.Successor = paypalPaymentHandler;
        paypalPaymentHandler.Successor = moneyPaymentHnadler;
 
        bankPaymentHandler.Handle(receiver);
 
        Console.Read();
    }
}
 
class Receiver
{
    // банковские переводы
    public bool BankTransfer { get; set; }
    // денежные переводы - WesternUnion, Unistream
    public bool MoneyTransfer { get; set; }
    // перевод через PayPal
    public bool PayPalTransfer { get; set; }
    public Receiver(bool bt, bool mt, bool ppt)
    {
        BankTransfer = bt;
        MoneyTransfer = mt;
        PayPalTransfer = ppt;
    }
}
abstract class PaymentHandler
{
    public PaymentHandler Successor { get; set; }
    public abstract void Handle(Receiver receiver);
}
 
class BankPaymentHandler : PaymentHandler
{
    public override void Handle(Receiver receiver)
    {
        if (receiver.BankTransfer == true)
            Console.WriteLine("Выполняем банковский перевод");
        else if (Successor != null)
            Successor.Handle(receiver);
    }
}
 
class PayPalPaymentHandler : PaymentHandler
{
    public override void Handle(Receiver receiver)
    {
        if (receiver.PayPalTransfer == true)
            Console.WriteLine("Выполняем перевод через PayPal");
        else if (Successor != null)
            Successor.Handle(receiver);
    }
}
// переводы с помощью системы денежных переводов
class MoneyPaymentHandler : PaymentHandler
{
    public override void Handle(Receiver receiver)
    {
        if (receiver.MoneyTransfer == true)
            Console.WriteLine("Выполняем перевод через системы денежных переводов");
        else if (Successor != null)
            Successor.Handle(receiver);
    }
}

 

Примеры в .NET Framework:

  • Событие Closing в Windows Forms с возможностью отмены закрытия формы путем установки свойства Cancel аргумента CancelEventArgs в True
  • Событие TaskScheduler.UnobservedException, обработчик которого может уведомить планировщик, что необработанное исключение задачи не является критическим, путем вызова метода UnobservedTaskExceptionEventArgs.SetObserved. Для аналогичных целей используются события Contract.ContractFailed и Application.DispatcherUnhandledException.

Comments:

Please log in to be able add comments.
👍