Sobes.tech
Назад к вопросам
Junior — Middle
60

Можешь привести пример реализации паттерна Chain of Responsibility в программном коде?

Компании, где спрашивали
AstonAston

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Паттерн Chain of Responsibility позволяет передавать запрос по цепочке обработчиков, пока один из них не возьмёт его на себя. Это удобно, когда заранее неизвестно, какой именно компонент должен обработать запрос. Важно показать, как обработчики связаны между собой и как запрос проходит по цепочке.

Определение:

Chain of Responsibility — это поведенческий паттерн, в котором запрос передаётся от одного обработчика к следующему, пока не будет найден подходящий обработчик или пока цепочка не закончится. Каждый обработчик либо обрабатывает запрос, либо передаёт его дальше.

Пример использования:

using System;

public abstract class Handler
{
    protected Handler? Next { get; private set; }

    public Handler SetNext(Handler next)
    {
        Next = next;
        return next;
    }

    public virtual void Handle(string request)
    {
        if (Next != null)
            Next.Handle(request);
    }
}

public class AuthHandler : Handler
{
    public override void Handle(string request)
    {
        if (request == "auth")
        {
            Console.WriteLine("Запрос обработан: авторизация");
            return;
        }

        base.Handle(request);
    }
}

public class LoggingHandler : Handler
{
    public override void Handle(string request)
    {
        if (request == "log")
        {
            Console.WriteLine("Запрос обработан: логирование");
            return;
        }

        base.Handle(request);
    }
}

public class DefaultHandler : Handler
{
    public override void Handle(string request)
    {
        Console.WriteLine($"Запрос не распознан: {request}");
    }
}

public class Program
{
    public static void Main()
    {
        var auth = new AuthHandler();
        var log = new LoggingHandler();
        var fallback = new DefaultHandler();

        auth.SetNext(log).SetNext(fallback);

        auth.Handle("log");
        auth.Handle("auth");
        auth.Handle("unknown");
    }
}

Пояснение кода:

Код строит цепочку из трёх обработчиков: AuthHandler -> LoggingHandler -> DefaultHandler.

  1. Handler — базовый класс с ссылкой на следующий обработчик.
  2. Метод SetNext связывает элементы цепочки и возвращает переданный обработчик, чтобы удобно строить цепочку вызовами подряд.
  3. Каждый наследник переопределяет Handle:
    • если запрос подходит, он обрабатывает его сам;
    • если не подходит, вызывает base.Handle(request), передавая запрос дальше.
  4. AuthHandler обрабатывает строку "auth".
  5. LoggingHandler обрабатывает строку "log".
  6. DefaultHandler срабатывает как запасной вариант, если никто раньше не обработал запрос.
  7. В Main один и тот же запрос передаётся в начало цепочки, а дальше он проходит по обработчикам до подходящего.

Ключевые моменты:

  • Паттерн уменьшает жёсткую связанность между отправителем запроса и его обработчиками.
  • Каждый обработчик решает: обработать запрос или передать дальше.
  • Цепочка может быть сколь угодно длинной и настраиваться динамически.
  • Удобен для валидации, middleware, обработки событий, прав доступа и маршрутизации.
  • Важно предусмотреть обработчик по умолчанию или корректное завершение цепочки.