Поведенческие паттерны: Strategy, Chain of Responsibility, Command, Observer, Template Method, Mediator
↑ 8.1 Принципы и паттерны проектирования в C♯ · ← Предыдущая · → Следующая
Зачем это на собесе
Самые применимые паттерны: Strategy, Observer, Mediator, Chain — встречаются в ASP.NET Core и MediatR.
Объяснение
| Паттерн | Суть | Где встречается |
|---|---|---|
| Strategy | взаимозаменяемые алгоритмы за интерфейсом | расчёт скидок, способы оплаты, IComparer |
| Chain of Responsibility | запрос проходит по цепочке обработчиков | middleware ASP.NET Core, DelegatingHandler |
| Command | запрос как объект: можно очередить, логировать, отменять | CQRS-команды, ICommand |
| Observer | подписчики получают уведомления | события C#, IObservable<T>, доменные события |
| Template Method | скелет алгоритма в базовом классе, шаги переопределяются | BackgroundService, базовые обработчики |
| Mediator | объекты общаются через посредника | MediatR |
| State | поведение зависит от состояния | конечные автоматы заказа |
| Iterator | обход коллекции | IEnumerable, yield |
| Visitor | операция над структурой без её изменения | обход AST, ExpressionVisitor |
| Memento | сохранение состояния для отката | undo |
// Strategy + DI: набор стратегий, выбор по условию
public interface IShipping { bool Supports(string code); decimal Cost(Order o); }
public class ShippingCalculator(IEnumerable<IShipping> all)
{
public decimal Cost(Order o, string code) => all.First(s => s.Supports(code)).Cost(o);
}
// Chain of Responsibility: пайплайн шагов обработки
public delegate Task Step(OrderContext ctx, Func<Task> next);
Step[] pipeline = [Validate, Reserve, Charge];
// Mediator: обработчик команды
public record CreateOrder(Guid CustomerId) : IRequest<Guid>;
public class CreateOrderHandler : IRequestHandler<CreateOrder, Guid> { /* ... */ }
var id = await mediator.Send(new CreateOrder(customerId));
// Observer: доменное событие
public event Func<OrderPaid, Task>? OrderPaid;Нюансы и подводные камни
- Observer с событиями C#: утечки памяти при неотписанных подписчиках (сильные ссылки).
- Mediator скрывает зависимости между компонентами; в больших системах затрудняет навигацию по коду.
- Strategy с
if/elseв фабрике сводит пользу к нулю: выбирайте через DI/ключи. - Command объекты должны быть сериализуемыми, если уходят в очередь.
Практика
- Замените цепочку
if/elseрасчёта доставки на стратегии. - Реализуйте свой мини-pipeline обработки заказа (Chain).
- Сделайте конечный автомат статуса заказа (State).
Вопросы с ответами
Где в ASP.NET Core используется Chain of Responsibility?
В конвейере middleware.
Strategy или State?
Strategy выбирает алгоритм снаружи; State меняет поведение объекта по его внутреннему состоянию.
Что делает Mediator?
Централизует взаимодействие компонентов, чтобы они не знали друг о друге.