Комментарии 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>();Выпячивать потомкам поля в принципе плохо (лучше свойства), ну а уж поля, которые полностью могут искорежить логику родителя - вдвойне плохо.
Правила именования для protected членов такие же, как и для public. Здесь имя должно быть "Children".
Ну и писать имя класса в конструкторе в 2025 году - такое себе.
Для создания матрешки декораторов крайне желателен механизм fluent builder, но тут об этом никто не позаботился.
Идем дальше:
_component.Execute();
foreach (var child in _children)
{
child.Execute();
}Этот код намекает, что как-бы отдельно _component держать не надо, достаточно его просто в коллекцию положить. Можно возразить, что при нескольких уровнях наследования это будет работать по-другому, но автор, кстати, здесь вообще вопрос наследования не рассматривает.
В целом вообще непонятно, как регулировать порядок выполнения PreExecute, Execute и PostExecute во вложенных декораторах. Автор дает только один вариант и не факт, что он во всех случаях подойдет.
И тут дан пример только с одним методом, а если их будет несколько десятков? Как все это все будет выглядеть?
А как это все должно работать, если методы должны что-то возвращать?
Фрактальный декоратор в C#