Перейти к содержанию

ChainOfResponsibility.cs

Код подключён напрямую из исходного файла в кодировке UTF-8, поэтому эта страница всегда показывает его актуальную версию.

← К конспекту Скачать исходный файл

ChainOfResponsibility.cs
using System;

namespace DesignPatterns.Behavioral.ChainOfResponsibility
{
    public sealed class SupportTicket
    {
        public string Description { get; }
        public int SeverityLevel { get; } // 1 - низкий, 3 - критический

        public SupportTicket(string description, int severityLevel)
        {
            Description = description;
            SeverityLevel = severityLevel;
        }
    }

    // Общий интерфейс обработчика - и сам обрабатывает запрос, и хранит ссылку
    // на следующего обработчика в цепочке.
    public abstract class SupportHandler
    {
        private SupportHandler? _next;

        // Возвращаем handler, чтобы можно было строить цепочку одной цепочкой вызовов
        public SupportHandler SetNext(SupportHandler next)
        {
            _next = next;
            return next;
        }

        public void Handle(SupportTicket ticket)
        {
            if (CanHandle(ticket))
            {
                Process(ticket);
                return;
            }

            if (_next is not null)
            {
                _next.Handle(ticket);
            }
            else
            {
                Console.WriteLine($"Тикет «{ticket.Description}» никто не смог обработать");
            }
        }

        protected abstract bool CanHandle(SupportTicket ticket);
        protected abstract void Process(SupportTicket ticket);
    }

    public sealed class FirstLineSupport : SupportHandler
    {
        protected override bool CanHandle(SupportTicket ticket) => ticket.SeverityLevel == 1;

        protected override void Process(SupportTicket ticket) =>
            Console.WriteLine($"[Первая линия] Обработан: {ticket.Description}");
    }

    public sealed class SecondLineSupport : SupportHandler
    {
        protected override bool CanHandle(SupportTicket ticket) => ticket.SeverityLevel == 2;

        protected override void Process(SupportTicket ticket) =>
            Console.WriteLine($"[Вторая линия] Обработан: {ticket.Description}");
    }

    public sealed class EngineeringTeam : SupportHandler
    {
        protected override bool CanHandle(SupportTicket ticket) => ticket.SeverityLevel >= 3;

        protected override void Process(SupportTicket ticket) =>
            Console.WriteLine($"[Инженеры] Обработан критический тикет: {ticket.Description}");
    }

    public static class Demo
    {
        public static void Run()
        {
            var firstLine = new FirstLineSupport();
            var secondLine = new SecondLineSupport();
            var engineering = new EngineeringTeam();

            // Строим цепочку: первая линия -> вторая линия -> инженеры
            firstLine.SetNext(secondLine).SetNext(engineering);

            firstLine.Handle(new SupportTicket("Не приходит письмо", severityLevel: 1));
            firstLine.Handle(new SupportTicket("Ошибка в отчёте", severityLevel: 2));
            firstLine.Handle(new SupportTicket("Сервис недоступен", severityLevel: 3));
        }
    }
}