Proxy + Поведенческие паттерны
Теория: Proxy (структурный паттерн)
Когда Proxy реально нужен
Когда Proxy реально нужен
Когда Proxy реально нужен
Когда Proxy реально нужен
Участники паттерна Proxy
Мини-пример в контексте магазина
Важное отличие от Decorator
Product — модель данных (не участник паттерна)
Subject (общий интерфейс) — IProductCatalog
RealSubject (реальный объект) — RealProductCatalog
RealSubject (реальный объект) — RealProductCatalog
Proxy (заместитель) — CachedProductCatalogProxy
Proxy (заместитель) — CachedProductCatalogProxy
Client (клиент) — будет в коде запуска
Client (клиент) — будет в коде запуска
Вывод
Поведенческие паттерны
Что значит поведенческий?
Chain of Responsibility (Цепочка обязанностей)
Пример в магазине
Практический пример
Практический пример
Практический пример
Практический пример
Практический пример
Command (Команда)
Пример в магазине
Command — команды корзины
Command — пример
Command — пример
Command — пример
Command — пример
Command — пример
Command — пример
Command — пример
Command — пример
State (Состояние)
Пример в магазине
State (Состояние) - Пример
State (Состояние) - Пример
State (Состояние) - Пример
State (Состояние) - Пример
State (Состояние) - Пример
State (Состояние) - Пример
State (Состояние) - Пример
Template Method (Шаблонный метод)+пример
Практический пример
Практический пример
Практический пример
Mediator (Посредник)+Пример в магазине
Практический пример
Практический пример
Практический пример
Практический пример
Практический пример
Практический пример
итог
Выполни практическое задание на выбор
Практическое задание
Практическое задание
Практическое задание
Практическое задание
127.14K
Category: programmingprogramming

Proxy + поведенческие паттерны. Урок 9-10

1. Proxy + Поведенческие паттерны

PROXY + ПОВЕДЕНЧЕСКИЕ
ПАТТЕРНЫ
Урок 9-10

2. Теория: Proxy (структурный паттерн)

ТЕОРИЯ: PROXY (СТРУКТУРНЫЙ
ПАТТЕРН)
• Что такое Proxy
• Proxy (Заместитель) — это объект, который “стоит между” клиентом и
реальным объектом и контролирует доступ к нему.
• То есть клиент работает не напрямую с RealObject, а через Proxy.

3. Когда Proxy реально нужен

КОГДА PROXY РЕАЛЬНО НУЖЕН
Proxy полезен, когда:
• Объект дорогой в создании
Например:
• загрузка изображения с диска
• подключение к API
• запрос в базу
• генерация PDF
Proxy делает ленивую загрузку (Lazy loading)

4. Когда Proxy реально нужен

КОГДА PROXY РЕАЛЬНО НУЖЕН
Нужно ограничить доступ
Например:
• только админ может удалить заказ
• только авторизованный пользователь может оплатить
Proxy = защита (Protection Proxy)

5. Когда Proxy реально нужен

КОГДА PROXY РЕАЛЬНО НУЖЕН
Нужно логирование
Например:
• логировать каждую операцию “Оплата заказа”
• считать статистику
Proxy = logging proxy

6. Когда Proxy реально нужен

КОГДА PROXY РЕАЛЬНО НУЖЕН
Нужно кеширование
Например:
• запрос “каталог товаров” одинаковый
• запрос “прайс” повторяется
Proxy хранит результат

7. Участники паттерна Proxy

УЧАСТНИКИ ПАТТЕРНА PROXY
• Subject — общий интерфейс
• RealSubject — реальный объект, который делает работу
• Proxy — объект-заместитель, который:
• хранит ссылку на RealSubject
• решает, когда создавать/вызывать RealSubject
• Client — работает через Subject

8. Мини-пример в контексте магазина

МИНИ-ПРИМЕР В КОНТЕКСТЕ
МАГАЗИНА
• Сервис каталога товаров:
• RealCatalogService делает запрос к базе (дорого)
• ProxyCatalogService кеширует результат на 10 секунд

9. Важное отличие от Decorator

ВАЖНОЕ ОТЛИЧИЕ ОТ DECORATOR
Оба “оборачивают объект”, но:
• Decorator добавляет функциональность и обычно их можно “наслаивать”
• Proxy контролирует доступ и часто скрывает факт существования
RealObject

10. Product — модель данных (не участник паттерна)

PRODUCT — МОДЕЛЬ ДАННЫХ (НЕ
УЧАСТНИК ПАТТЕРНА)
• Это просто сущность предметной области.
public record Product(int Id, string Name, decimal
Price);

11. Subject (общий интерфейс) — IProductCatalog

SUBJECT (ОБЩИЙ ИНТЕРФЕЙС) —
IPRODUCTCATALOG
• Роль в Proxy: Subject определяет общий интерфейс, с которым работает
клиент.
public interface IProductCatalog
{
IReadOnlyList<Product> GetProducts();
}
Важно:
• И RealProductCatalog, и CachedProductCatalogProxy реализуют этот
интерфейс.
• Это позволяет клиенту не знать, работает он с реальным объектом или с
Proxy.

12. RealSubject (реальный объект) — RealProductCatalog

REALSUBJECT (РЕАЛЬНЫЙ ОБЪЕКТ) —
REALPRODUCTCATALOG
public class RealProductCatalog : IProductCatalog
{
public IReadOnlyList<Product> GetProducts()
{
Console.WriteLine("[RealProductCatalog] Loading products from DB...");
Thread.Sleep(1000); // имитация дорогой операции
return new List<Product>
{
new Product(1, "Keyboard", 2500),
new Product(2, "Mouse", 1200),
new Product(3, "Monitor", 19990),
};
}
}

13. RealSubject (реальный объект) — RealProductCatalog

REALSUBJECT (РЕАЛЬНЫЙ ОБЪЕКТ) —
REALPRODUCTCATALOG
• RealSubject — объект, который делает настоящую работу.
• Здесь “дорогая операция” — это Thread.Sleep(1000)
• (как будто запрос в базу или API).

14. Proxy (заместитель) — CachedProductCatalogProxy

PROXY (ЗАМЕСТИТЕЛЬ) —
CACHEDPRODUCTCATALOGPROXY
• Proxy контролирует доступ к RealSubject.
• В этом примере Proxy выполняет задачу: кеширование результата на 5
секунд (TTL)
Ключевой момент:
Proxy решает:
• можно ли вернуть кеш
• или нужно идти в RealSubject

15. Proxy (заместитель) — CachedProductCatalogProxy

PROXY (ЗАМЕСТИТЕЛЬ) —
CACHEDPRODUCTCATALOGPROXY
public class CachedProductCatalogProxy :
IProductCatalog
public IReadOnlyList<Product> GetProducts()
{
{
private readonly IProductCatalog _real;
ссылка на RealSubject
//
private IReadOnlyList<Product>? _cache;
кеш результата
//
private DateTime _cacheTime;
время кеширования
//
if (_cache != null && DateTime.Now _cacheTime < _ttl)
{
Console.WriteLine("[Proxy] Return
products from cache");
return _cache;
}
private readonly TimeSpan _ttl =
TimeSpan.FromSeconds(5);
Console.WriteLine("[Proxy] Cache is empty or
expired -> call RealProductCatalog");
_cache = _real.GetProducts();
public CachedProductCatalogProxy(IProductCatalog
real)
_cacheTime = DateTime.Now;
{
return _cache;
_real = real;
}
}
}

16. Client (клиент) — будет в коде запуска

CLIENT (КЛИЕНТ) — БУДЕТ В КОДЕ
ЗАПУСКА
Роль: Клиент работает с интерфейсом IProductCatalog и не обязан знать,
что там Proxy.
• 1-й вызов → реальная загрузка (1 сек)
• 2-й вызов → кеш (мгновенно)
• ждём 6 секунд → кеш протух
• 3-й вызов → снова реальная загрузка

17. Client (клиент) — будет в коде запуска

CLIENT (КЛИЕНТ) — БУДЕТ В КОДЕ
ЗАПУСКА
public class Program
{
===");
public static void Main()
Console.WriteLine("\n=== Wait 6 seconds (cache expires)
Thread.Sleep(6000);
{
// Client работает через интерфейс Subject
IProductCatalog catalog = new
CachedProductCatalogProxy(
===");
Console.WriteLine("\n=== Third call (cache expired)
var products3 = catalog.GetProducts();
new RealProductCatalog()
Print(products3);
);
}
Console.WriteLine("=== First call ===");
private static void Print(IReadOnlyList<Product> products)
var products1 = catalog.GetProducts();
{
Print(products1);
foreach (var p in products)
Console.WriteLine($"{p.Id}. {p.Name} - {p.Price}");
Console.WriteLine("\n=== Second call (cache) ===");
var products2 = catalog.GetProducts();
Print(products2);
}
}

18. Вывод

ВЫВОД
Client вызывает GetProducts()
но:
• иногда запрос реально идёт в RealProductCatalog
• иногда Proxy возвращает кеш
• Client при этом не меняется вообще

19. Поведенческие паттерны

ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ

20. Что значит поведенческий?

ЧТО ЗНАЧИТ ПОВЕДЕНЧЕСКИЙ?
• Паттерны поведения управляют различными вариантами поведения
системы объектов

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

CHAIN OF RESPONSIBILITY (ЦЕПОЧКА
ОБЯЗАННОСТЕЙ)
• Объект отправляет запрос, не зная, кто его обработает.
Запрос проходит по цепочке обработчиков, пока кто-то не обработает
• Участники
• Handler — интерфейс обработки
• ConcreteHandler — конкретный обработчик
• successor — ссылка на следующий обработчик
• Client — инициирует запрос

22. Пример в магазине

ПРИМЕР В МАГАЗИНЕ
• Проверка заказа перед оплатой:
• Цепочка:
• Проверка наличия товаров
• Проверка возраста (если товар 18+)
• Проверка баланса / лимита
• Проверка доставки

23. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class Order
{
public int CustomerAge { get; set; }
public List<Product> Items { get; set; } = new();
public decimal Total => Items.Sum(i => i.Price);
}

24. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public abstract class OrderCheckHandler
{
{
if (!Check(order))
protected OrderCheckHandler? Next;
throw new
Exception($"{GetType().Name}: check
failed!");
public OrderCheckHandler
SetNext(OrderCheckHandler next)
Next?.Handle(order);
{
}
Next = next;
return next;
}
protected abstract bool Check(Order
order);
}
public void Handle(Order order)

25. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class StockCheckHandler : OrderCheckHandler
{
protected override bool Check(Order order)
{
Console.WriteLine("[StockCheck] OK (demo always
true)");
return order.Items.Count > 0;
}
}

26. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class MinPriceCheckHandler : OrderCheckHandler
{
private readonly decimal _minPrice;
public MinPriceCheckHandler(decimal minPrice)
{
_minPrice = minPrice;
}
protected override bool Check(Order order)
{
Console.WriteLine($"[MinPriceCheck] Total={order.Total}, Min={_minPrice}");
return order.Total >= _minPrice;
}
}

27. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class AgeCheckHandler : OrderCheckHandler
{
protected override bool Check(Order order)
{
bool has18Plus = order.Items.Any(p => p.Name.Contains("18+"));
if (!has18Plus)
{
Console.WriteLine("[AgeCheck] No 18+ items -> OK");
return true;
}
Console.WriteLine($"[AgeCheck] CustomerAge={order.CustomerAge}");
return order.CustomerAge >= 18;
}
}

28. Command (Команда)

COMMAND (КОМАНДА)
• Команда — это объект.
Она инкапсулирует действие, позволяет:
• ставить команды в очередь
• отменять
• выполнять по расписанию
• Участники
• Command — интерфейс Execute()
• ConcreteCommand — конкретная команда
• Receiver — тот, кто реально выполняет действие
• Invoker — вызывает Execute()

29. Пример в магазине

ПРИМЕР В МАГАЗИНЕ
• Команды:
• AddToCartCommand
• RemoveFromCartCommand
• ApplyPromoCommand
• CheckoutCommand
• Можно сделать undo для корзины.

30. Command — команды корзины

COMMAND — КОМАНДЫ КОРЗИНЫ
• Command = объект действия
• Receiver = Cart
• Invoker = CartController

31. Command — пример

COMMAND — ПРИМЕР
public class Cart
public void Clear()
{
{
private readonly List<Product> _items = new();
_items.Clear();
Console.WriteLine("[Cart] Cleared");
public void Add(Product p)
}
{
_items.Add(p);
public void Print()
Console.WriteLine($"[Cart] Added: {p.Name}");
{
}
Console.WriteLine("Cart:");
foreach (var item in _items)
public void Remove(Product p)
Console.WriteLine($" - {item.Name} ({item.Price})");
{
_items.Remove(p);
Console.WriteLine($"Total: {_items.Sum(i => i.Price)}");
Console.WriteLine($"[Cart] Removed: {p.Name}");
}
}
}

32. Command — пример

COMMAND — ПРИМЕР
public interface ICommand
{
void Execute();
}

33. Command — пример

COMMAND — ПРИМЕР
public class AddToCartCommand : ICommand
{
private readonly Cart _cart;
private readonly Product _product;
public AddToCartCommand(Cart cart, Product product)
{
_cart = cart;
_product = product;
}
public void Execute() => _cart.Add(_product);
}

34. Command — пример

COMMAND — ПРИМЕР
public class AddToCartCommand : ICommand
{
private readonly Cart _cart;
private readonly Product _product;
public AddToCartCommand(Cart cart, Product product)
{
_cart = cart;
_product = product;
}
public void Execute() => _cart.Add(_product);
}

35. Command — пример

COMMAND — ПРИМЕР
public class RemoveFromCartCommand : ICommand
{
private readonly Cart _cart;
private readonly Product _product;
public RemoveFromCartCommand(Cart cart, Product product)
{
_cart = cart;
_product = product;
}
public void Execute() => _cart.Remove(_product);
}

36. Command — пример

COMMAND — ПРИМЕР
public class RemoveFromCartCommand : ICommand
{
private readonly Cart _cart;
private readonly Product _product;
public RemoveFromCartCommand(Cart cart, Product product)
{
_cart = cart;
_product = product;
}
public void Execute() => _cart.Remove(_product);
}

37. Command — пример

COMMAND — ПРИМЕР
public class ClearCartCommand : ICommand
{
private readonly Cart _cart;
public ClearCartCommand(Cart cart)
{
_cart = cart;
}
public void Execute() => _cart.Clear();
}

38. Command — пример

COMMAND — ПРИМЕР
public class CartController // Invoker
{
public void Run(ICommand command)
{
Console.WriteLine("[Invoker] Execute
command...");
command.Execute();
}
}

39. State (Состояние)

STATE (СОСТОЯНИЕ)
• Состояния объекта выделяются в отдельные классы.
Каждый класс состояния реализует поведение по-своему
• Участники
• Context — объект, у которого есть состояние
• State — интерфейс поведения
• ConcreteState — конкретные состояния

40. Пример в магазине

ПРИМЕР В МАГАЗИНЕ
• Заказ может быть:
• New
• Paid
• Shipped
• Delivered
• Cancelled
• И в каждом состоянии:
• разрешены разные действия
• разные переходы

41. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
Заказ меняет поведение в зависимости от состояния.
public interface IOrderState
{
void Pay(OrderContext order);
void Ship(OrderContext order);
void Deliver(OrderContext order);
void Cancel(OrderContext order);
string Name { get; }
}

42. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class OrderContext
{
private IOrderState _state;
public OrderContext()
{
_state = new
CreatedState();
}
public void
SetState(IOrderState state)
{
_state = state;
Console.WriteLine($"[Order]
State -> {_state.Name}");
}
public void Pay() =>
_state.Pay(this);
public void Ship() =>
_state.Ship(this);
public void Deliver() =>
_state.Deliver(this);
public void Cancel() =>
_state.Cancel(this);
}

43. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class CreatedState : IOrderState
paid");
{
public string Name => "Created";
public void Pay(OrderContext order)
public void Deliver(OrderContext order) =>
Console.WriteLine("[Created] Cannot deliver: not
shipped");
{
public void Cancel(OrderContext order)
Console.WriteLine("[Created] Payment accepted");
{
order.SetState(new PaidState());
Console.WriteLine("[Created] Cancelled");
}
order.SetState(new CancelledState());
public void Ship(OrderContext order) =>
Console.WriteLine("[Created] Cannot ship: not
}
}

44. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class PaidState : IOrderState
{
public string Name => "Paid";
=>
public void Deliver(OrderContext order)
Console.WriteLine("[Paid] Cannot
deliver: not shipped");
public void Pay(OrderContext order) =>
paid");
Console.WriteLine("[Paid] Already
public void Cancel(OrderContext order)
{
public void Ship(OrderContext order)
{
Console.WriteLine("[Paid]
Shipped");
Console.WriteLine("[Paid] Cancelled
(refund)");
order.SetState(new
CancelledState());
order.SetState(new ShippedState()); }
}
}

45. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class ShippedState : IOrderState
{
public string Name => "Shipped";
=>
public void Pay(OrderContext order)
public void Deliver(OrderContext
order)
{
Console.WriteLine("[Shipped]
Delivered");
order.SetState(new
DeliveredState());
Console.WriteLine("[Shipped]
Already paid");
=>
}
public void Cancel(OrderContext
public void Ship(OrderContext order) order) =>
Console.WriteLine("[Shipped]
Already shipped");
Console.WriteLine("[Shipped]
Cannot cancel: already shipped");
}

46. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class DeliveredState :
IOrderState
{
public string Name => "Delivered";
public void Deliver(OrderContext
order) =>
Console.WriteLine("[Delivered]
Already delivered");
public void Pay(OrderContext order)
=>
Console.WriteLine("[Delivered]
Already finished");
public void Ship(OrderContext order)
=>
Console.WriteLine("[Delivered]
Already finished");
public void Cancel(OrderContext
order) =>
Console.WriteLine("[Delivered]
Cannot cancel: already delivered");
}

47. State (Состояние) - Пример

STATE (СОСТОЯНИЕ) - ПРИМЕР
public class CancelledState :
IOrderState
{
public string Name => "Cancelled";
public void Deliver(OrderContext
order) =>
Console.WriteLine("[Cancelled]
Cannot deliver: cancelled");
public void Pay(OrderContext order)
=>
Console.WriteLine("[Cancelled]
Cannot pay: cancelled");
public void Ship(OrderContext order)
=>
Console.WriteLine("[Cancelled]
Cannot ship: cancelled");
public void Cancel(OrderContext
order) =>
Console.WriteLine("[Cancelled]
Already cancelled");
}

48. Template Method (Шаблонный метод)+пример

TEMPLATE METHOD (ШАБЛОННЫЙ
МЕТОД)+ПРИМЕР
Есть абстрактный класс с алгоритмом (скелетом).
Часть шагов реализуют наследники
Процесс оплаты:
Алгоритм:
ValidateOrder()
ReserveProducts()
Pay()
SendReceipt()
Наследники:
CardPaymentProcessor
CryptoPaymentProcessor
CashPaymentProcessor

49. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
Есть скелет алгоритма “Checkout”, шаги
переопределяются.
public abstract class CheckoutProcess
protected virtual void Reserve(Order
order)
{
{
public void Checkout(Order order)
{
Console.WriteLine("[Checkout]
Reserve items");
}
Validate(order);
Reserve(order);
Pay(order);
protected abstract void Pay(Order
order);
Notify(order);
}
protected virtual void Validate(Order
order)
{
Console.WriteLine("[Checkout]
Validate order");
}
protected virtual void Notify(Order
order)
{
Console.WriteLine("[Checkout] Send
notification");
}
}

50. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class CardCheckout : CheckoutProcess
{
protected override void Pay(Order order)
{
Console.WriteLine("[CardCheckout] Pay by
card");
}
}

51. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class CashCheckout : CheckoutProcess
{
protected override void Pay(Order order)
{
Console.WriteLine("[CashCheckout] Pay by cash
on delivery");
}
}

52. Mediator (Посредник)+Пример в магазине

MEDIATOR (ПОСРЕДНИК)+ПРИМЕР В
МАГАЗИНЕ
• Вместо “хаоса связей” между объектами — один объект Mediator
координирует изменения состояний группы объектов
• Компоненты UI или подсистемы:
• Cart
• Warehouse
• Payment
• Delivery
• Вместо того чтобы Cart напрямую дергал Payment и Warehouse — есть
OrderMediator.

53. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public interface IShopMediator
{
void Notify(object sender, string ev);
}

54. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class CartSubsystem
{
private readonly IShopMediator _mediator;
public CartSubsystem(IShopMediator mediator)
{
_mediator = mediator;
}
public void Checkout()
{
Console.WriteLine("[Cart] Checkout clicked");
_mediator.Notify(this, "checkout");
}
}

55. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class WarehouseSubsystem
{
public bool ReserveItems()
{
Console.WriteLine("[Warehouse] Items
reserved");
return true;
}
}

56. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class PaymentSubsystem
{
public bool Pay()
{
Console.WriteLine("[Payment] Payment OK");
return true;
}
}

57. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class DeliverySubsystem
{
public void CreateDelivery()
{
Console.WriteLine("[Delivery] Delivery
created");
}
}

58. Практический пример

ПРАКТИЧЕСКИЙ ПРИМЕР
public class OrderMediator : IShopMediator
Console.WriteLine("[Mediator] Start checkout process");
{
private readonly WarehouseSubsystem _warehouse;
if (!_warehouse.ReserveItems())
private readonly PaymentSubsystem _payment;
{
private readonly DeliverySubsystem _delivery;
Console.WriteLine("[Mediator] Cannot reserve items");
return;
public OrderMediator(
}
WarehouseSubsystem warehouse,
PaymentSubsystem payment,
if (!_payment.Pay())
DeliverySubsystem delivery)
{
{
Console.WriteLine("[Mediator] Payment failed");
_warehouse = warehouse;
return;
_payment = payment;
}
_delivery = delivery;
}
_delivery.CreateDelivery();
Console.WriteLine("[Mediator] Order completed!");
public void Notify(object sender, string ev)
}
{
}
if (ev == "checkout")
{
}

59. итог

ИТОГ
Proxy
• Зачем: контроль доступа к объекту.
• Применение: кеш, защита, логирование, ленивая
загрузка.
Chain of Responsibility
• Зачем: передавать запрос по цепочке обработчиков.
• Применение: проверки, фильтры, middleware.
Command
• Зачем: превратить действие в объект.
• Применение: undo/redo, очередь команд, макросы.
State
• Зачем: вынести поведение по состояниям в отдельные
классы.
• Применение: заказ, доставка, пользовательские
статусы.
Template Method
• Зачем: общий алгоритм + разные шаги.
• Применение: обработка платежей, оформление
заказа, импорт данных.
Mediator
• Зачем: уменьшить связность между объектами.
• Применение: координация подсистем
(корзина/оплата/склад).

60. Выполни практическое задание на выбор

ВЫПОЛНИ ПРАКТИЧЕСКОЕ
ЗАДАНИЕ НА ВЫБОР

61. Практическое задание

ПРАКТИЧЕСКОЕ ЗАДАНИЕ
• Proxy + State (Заказ и его жизненный цикл)
State Сделать заказ с состояниями:
• Created
В разных состояниях методы ведут себя поразному.
2) Proxy Сделать OrderServiceProxy, который:
• Paid
• проверяет авторизацию пользователя
• Shipped
• логирует вызовы методов
• Delivered
• только потом вызывает OrderService
• Cancelled
Методы:
• Pay()
• Ship()
• Deliver()
• Cancel()

62. Практическое задание

ПРАКТИЧЕСКОЕ ЗАДАНИЕ
• Chain of Responsibility + Template Method (Оформление заказа)
1) Chain of Responsibility Сделать цепочку проверок перед оплатой:
CheckStockHandler
CheckMinOrderPriceHandler
CheckAgeHandler (если товар 18+)
CheckDeliveryHandler
2) Template Method Сделать базовый класс CheckoutProcess:
Validate()
Reserve()
Pay()
Notify()
Наследники:
PickupCheckout
DeliveryCheckout

63. Практическое задание

ПРАКТИЧЕСКОЕ ЗАДАНИЕ
• Mediator + Command (Оркестратор заказа)
1) Mediator Есть подсистемы:
2) Command Команды:
• PlaceOrderCommand
• Cart
• PayOrderCommand
• Warehouse
• CancelOrderCommand
• Payment
• Delivery
• Они не должны общаться напрямую.
• Только через OrderMediator.
• Invoker вызывает команды, команды дергают
Mediator.

64. Практическое задание

ПРАКТИЧЕСКОЕ ЗАДАНИЕ
• Proxy + Chain of Responsibility (Защита и проверки)
1) Proxy Сделать AdminPanelProxy, который:
• проверяет роль пользователя (admin/user)
• если user → запрет на удаление товара
2) Chain of Responsibility Удаление товара проходит цепочку:
• ValidateIdHandler
• CheckPermissionsHandler
• CheckProductExistsHandler
• DeleteProductHandler
English     Русский Rules