@vVega

Как выбирать действие в зависимости от типа объекта?

В проекте есть класс с единственным статическим методом, который получает из статической фабрики объект и запускает нужное действие в зависимости от переданного статуса.
class Executor
{
    public static function runActionByStatus(int $id, string $status): void
    {
        $object = Factory::create($id);

        if ($status === 'create') {
            $object->create();
        }

        if ($status === 'cancel') {
            $object->cancel();
        }

        if ($status === 'commit') {
            $object->commit();
        }
    }
}


До текущего момента фабрика всегда создавала объекты одного типа. Теперь объекты, которые создает фабрика имеют подтипы. Требуется разный алгоритм выбора действия в зависимости от подтипа созданного фабрикой объекта (статусы разные для каждого подтипа).

Подскажите варианты рефакторинга.
  • Вопрос задан
  • 174 просмотра
Решения вопроса 1
xEpozZ
@xEpozZ
Веб-разработчик
> Теперь объекты, которые создает фабрика имеют подтипы. Требуется разный алгоритм выбора действия в зависимости от подтипа созданного фабрикой объекта

Значит фабрика у вас не должна ничего решать сама. Разные типы + разные действия = разные классы, фабрики.

1. Может проще создать парочку отдельные фабрик для этих подклассов и в нужном месте вызывать нужную, не ожидая, что какая-то стратегия правильно сматчит вам фабрику?
2. Если у вас еще одна фабрика появилась, то это не значит, что здесь супер узкое бутылочное горлышко и его нужно рефакторить. Тем более, если пока сами не знаете как лучше это сделать. Сделайте пару развилок через if. Когда появится больше запросов к этому коду, тогда и новое поведение подскажет, как всё-таки он должен выглядеть.
3. Если всё-таки хотите как-то отрефакторить сейчас, то вариант от vilinyh подойдет на первое время. А возможно и на всегда.
$object = Factory::create($id);
$action = ActionFactory::create($status, $object);
$action->run();

Только для ясности я бы его переписал так:
$factory = Factory::create($id);
$result = $factory->run($status);

Немного пояснений:
Factory::create() – отдаст вам фабрику по объекту. Там сделаете пару if на проверку типа.
$factory->run() – выполнит нужные действия уже в фабрике нужного класса.

4. А еще можно сделать методы не статическими, обернуть интерфейсам, инжектить через контейнер, сделать промежуточный AggregateFactory, который будет делать if $subFactory->supports() цикле по всем фабрикам, которые реализуют уже логику, умно отлавливать ошибки, логировать результаты и всё в этом духе. Почти стратегию и реализовали таким способом. Но вот только нужно оно вам сейчас? :)
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
delphinpro
@delphinpro Куратор тега PHP
frontend developer
Какая нафиг стратегия?
Создать, отменить и зафиксировать – это не три разные стратегии! Это три разных действия. Вам маршрутизатор нужен, вероятно.
Ответ написан
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
паттерн Strategy
Ответ написан
Комментировать
@Dark_Dante
Более того, if тут немного бессмысленен - статус то всегда один, т.е. отработает только один блок if. Я бы написал это через switch. Ну или хотя бы elseif
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы