← На главную портала
База знаний: SOLID & GRASP → ИТМО • 3 Семестр • ООП C#
Лабораторная №2 7/7 Тестов ТЗ GoF: Composite & Decorator Result Pattern (DU)

Правила распределения экземпляров по тарам

Интерактивный архитектурный гид: дерево правил распределения, реализация принципов SOLID и GRASP в коде, паттерны Composite и Decorator, товарное соседство, Result Pattern и вопросы по лекциям кафедры.

Сложность
⭐⭐⭐ Паттерны GoF
Сборка
0 ошибок / 0 warnings

🌳 Логика распределения: Дерево правил (Composite + Decorator)

Нажмите на любой узел для разбора реализации

По спецификации лабы вся логика распределения экземпляров строится в виде дерева через единый контракт IDistributionRule.

Маршрутизатор Router / Branch
CategoryRouterDistributionRule

Мапит категорию товара на дочернее правило. Если маппинга нет — вызывает правило по умолчанию.

Палета (Композит) Composite
PalletDistributionRule

Содержит коллекцию правил вложенных тар. Перебирает их до первого успешного размещения товара.

Декораторы Decorator
Expiration & Logging

Оборачивают любое правило, добавляя сквозную проверку срока годности или логирование исхода.

Лист (Листовое правило) Leaf
TareDistributionRule

Базовое листовое правило. Делегирует непосредственное размещение сервису TareService.

CategoryRouterDistributionRule Паттерн: Router / Strategy Selector

Позволяет конфигурировать правила в зависимости от категории товара. Например, отправлять «Электронику» в тару А, «ФРОВ» в тару Б, а все остальные категории — в общее дефолтное правило.

public DistributionResult Distribute(Item item)
{
    ArgumentNullException.ThrowIfNull(item);
    if (_routes.TryGetValue(item.Sku.Category.Id, out IDistributionRule? rule))
    {
        return rule.Distribute(item);
    }
    return _defaultRule.Distribute(item);
}

🛡️ Правило товарного соседства (Neighborhood)

Вынесено в отдельный сервис NeighborhoodValidator : INeighborhoodValidator по принципу единственной ответственности (SRP):

  • Товар с товарной группой: может лежать в таре только с товарами этой же самой группы.
  • Товар без товарной группы: может лежать в таре только с товарами, также не имеющими товарной группы.
  • Пустая тара: принимает любой первый товар (метод All(...) на пустой коллекции возвращает true).

📦 Result Pattern вместо Exceptions

Ошибки бизнес-логики (нехватка вместимости, конфликт товарного соседства, просрочка) не бросают исключений, а возвращают полиморфный результат:

abstract record TareAdditionResult { // private ctor }
├── Success : TareAdditionResult
├── CapacityExceeded : TareAdditionResult
├── NeighborhoodViolation : TareAdditionResult
└── TareNotFound : TareAdditionResult

Исключения (ArgumentException) используются строго в конструкторах для валидации инвариантов инициализации.