Как стать автором
Обновить

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

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

Можно заморочиться с типизированными сигналами (тогда класс сигнала будет его id, а внутри можно принеобходимости получать параметры)
Правда для качественного приема таких сигналов необходимо будет включать дополнительную инфраструктуру.
Мне стало самому интересно, и попробовал прикинуть
Можно реализовать типизированные сигналы вот так.
Получится много методов, но в авторской реализации все равно есть тот же switch
Заголовок спойлера
public class FSM {
    private IState state;

    public void Signal<T>(T signal) {
        var handler = state as IHandler<T>;
        if (handler == null) {
            Debug.LogWarning($"Current state {state.Name} is not support {typeof(T).Name} signal");
            return;
        }
        handler.HandleSignal(signal);
    }
}

public interface IHandler <T> {
    void HandleSignal(T signal);
}

public abstract class State : IState, IHandler<MessageA>, IHandler<MessageB>
{
    public void HandleSignal(MessageA signal)
    {
    }

    public void HandleSignal(MessageB signal)
    {
    }
}

public sealed class MessageA { }
public sealed class MessageB { }


public interface IState
{
    public string Name { get; }
}

Если ставить задачу избавиться от строковых ключей, в сигналах можно целиком заменить их enum, но это решение плохо масштабируется, мы просто утонем в его значениях. Также, можно использовать опыт разработчиков самой Unity с аниматорами, и брать хеш от этих же самых строк. Это слабо защищает от человеческого фактора, но полностью решает техническую сторону вопроса. В своем опыте я пробовал разные варианты, но пока плюсы работы со строковыми ключами перевесили, и не только в автоматах. И спасибо за обратную связь! Замечание, что тема раскрыта недостаточно, дельное. Эта статья долго зрела, но я не мог придумать, как преподнести тему максимально обще, чтобы она не выглядела как описание инструмента, полезного лишь в рамках конкретного стека. При возможности, я постараюсь раскрыть больше контекста и привести больше примеров решения тех или иных задач.

Выше вариант с типизированными ключами-классами
Масштабируется лучше enum.
А так мы тоже строковыми во многих подобных системах пользуемся.
Собственно, а для чего тогда в целом абстрактные сигналы в любом виде и проблемы с ними? Не лучше ли дать контроль над переходом самому стейту? пусть прям сам создаст следующий стейт и вернет его в апи контекста, и сразу же при создании использует сигнатуру его контруктора. В весьма масштабном проекте у меня получилось это использовать с приемлимыми показателями.

Сигналы — это интерфейс автомата. Через них мы передаем команды, но логика работы, правила переходов, как раз и описаны внутри состояний.

Да, согласен. Я не правильно выразился. Я хотел сказать что универсализация апи через сигналы а затем разворачивание обратно не обязательно для ФСМ. Как альтернатива — сделать интерфейс с конкретным и типизированным апи для автомата и реализовать его и в контексте (и пробрасывать сразу в текущий стейт) и в абстрактном стейте (пустыми реализациями например). И в необходимых реализациях уже самих стейтов оверрайдить методы на которые нужно реагировать. Тогда страшный свитч исчезнет, и сигнатуры все будут строгими.
Переходами управляет сам стейт, все верно.
Сигналы для обобщенной коммуникации со стейтом.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории