Обновить

Комментарии 7

Как будет выглядеть освобождение ресурсов? Например, внешний декоратор что-то выделил в Pre-execution, а в Post бы освободил. Но внутренний декоратор выкинул исключение. Post-Execute же не будет вызван?

Это можно поидее решить оверрайдом Execute-а и try/finally если сильно нужно, если я правильно понял

Тогда получается, что "Декоратор обработки исключений" обязателен и, чтобы не писать лапшу, у каждого уже исполненного декоратора он должен попытаться дернуть cleanup/handleException? А чтобы отработать по списку в обратном порядке надо либо в стэк записывать, либо текущий индекс списка декораторов пробрасывать и его с i до 0 проходить?

Пересмотрел код и комментарий, сам по себе оверрайд execute не поможет, потому что исключение может выпасть в соседнем блоке, см. дальше:

Хотя, если бы здесь действительно был рекурсивный алгоритм вызова декораторов (а не по списку, см. "// Главный метод Execute, реализующий рекурсивный вызов дочерних декораторов"), можно было бы обойтись try-catch на каждом(!) шагу, где нужен cleanup? Потом изнутри, как матрешка, исключение пробрасывается на верх.

У ChildExecutor-ов получается не будет возможности оверрайднуть выполнение, в отличие от классических декораторов, поскольку они вообще по сути на вход не получают "внутренние" компоненты. Да и получается что PreExecute для child-ов будет выполнен на самом деле уже после выполнения основного компонента... Странно это как-то.

Я честно говоря ожидал бы какого-нибудь построения рекурсивных делегатов или что-то вроде того

Зумеры изобретают джаву

Начнем со стиля. Странно видеть вот такие вещи:

protected readonly List<FractalDecorator> _children = new List<FractalDecorator>();
  1. Выпячивать потомкам поля в принципе плохо (лучше свойства), ну а уж поля, которые полностью могут искорежить логику родителя - вдвойне плохо.

  2. Правила именования для protected членов такие же, как и для public. Здесь имя должно быть "Children".

  3. Ну и писать имя класса в конструкторе в 2025 году - такое себе.

Для создания матрешки декораторов крайне желателен механизм fluent builder, но тут об этом никто не позаботился.

Идем дальше:

            _component.Execute();
            foreach (var child in _children)
            {
                child.Execute();
            }

Этот код намекает, что как-бы отдельно _component держать не надо, достаточно его просто в коллекцию положить. Можно возразить, что при нескольких уровнях наследования это будет работать по-другому, но автор, кстати, здесь вообще вопрос наследования не рассматривает.

В целом вообще непонятно, как регулировать порядок выполнения PreExecute, Execute и PostExecute во вложенных декораторах. Автор дает только один вариант и не факт, что он во всех случаях подойдет.

И тут дан пример только с одним методом, а если их будет несколько десятков? Как все это все будет выглядеть?

А как это все должно работать, если методы должны что-то возвращать?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS