如何在状态模式实现中优雅定义起始与结束状态间的最短幸福路径?
状态模式下优雅获取/描述最短幸福路径的方案
一、动态计算最短幸福路径(BFS实现)
如果你的状态转换逻辑可能频繁变动,用广度优先搜索(BFS)动态计算最短路径是更灵活的选择。它能自动适配状态类中的转换规则,无需硬编码路径。
实现代码
- 先提取所有状态的转换关系:
private static Dictionary<Type, List<(Type TargetStateType, string ActionName)>> GetStateTransitions(Entity entity) { var transitions = new Dictionary<Type, List<(Type, string)>>(); var stateTypes = new[] { typeof(StartState), typeof(StateA), typeof(StateB), typeof(EndState) }; foreach (var stateType in stateTypes) { var tempState = (State)Activator.CreateInstance(stateType, entity); var stateTransitions = new List<(Type, string)>(); if (tempState.Action1() != null) stateTransitions.Add((tempState.Action1().GetType(), nameof(State.Action1))); if (tempState.Action2() != null) stateTransitions.Add((tempState.Action2().GetType(), nameof(State.Action2))); if (tempState.Action3() != null) stateTransitions.Add((tempState.Action3().GetType(), nameof(State.Action3))); transitions[stateType] = stateTransitions; } return transitions; }
- 用BFS找最短路径:
public static List<(Type StateType, string ActionToNext)> FindShortestHappyPath(Entity entity) { var transitions = GetStateTransitions(entity); var startType = typeof(StartState); var endType = typeof(EndState); var queue = new Queue<Tuple<Type, List<(Type, string)>>>(); queue.Enqueue(Tuple.Create(startType, new List<(Type, string)>())); var visited = new HashSet<Type>(); visited.Add(startType); while (queue.Count > 0) { var current = queue.Dequeue(); var currentStateType = current.Item1; var currentPath = current.Item2; if (currentStateType == endType) { var fullPath = new List<(Type, string)>(); fullPath.Add((startType, null)); fullPath.AddRange(currentPath); return fullPath; } foreach (var transition in transitions[currentStateType]) { var targetType = transition.TargetStateType; if (!visited.Contains(targetType)) { visited.Add(targetType); var newPath = new List<(Type, string)>(currentPath); newPath.Add((targetType, transition.ActionName)); queue.Enqueue(Tuple.Create(targetType, newPath)); } } } return null; }
调用该方法后,你可以得到包含状态类型和对应动作的路径列表,既可以转换为前端需要的格式,也能用来自动导航(遍历路径调用对应Action)。
二、静态优雅描述幸福路径(类型安全方案)
如果状态转换逻辑稳定,用类型安全的静态方案更简洁,避免硬编码字符串导致的错误。
方案1:状态链式标记
给抽象State类添加幸福路径的下一个状态标记:
public abstract class State { protected Entity _entity; public State(Entity entity) { _entity = entity; } // 幸福路径的下一个状态及触发动作 public abstract (Type NextStateType, string ActionName)? NextHappyState { get; } // 原有Action方法不变 public abstract State Action1(); public abstract State Action2(); public abstract State Action3(); }
每个状态实现该属性:
public class StartState : State { public StartState(Entity entity) : base(entity) { } public override (Type, string)? NextHappyState => (typeof(StateA), nameof(Action1)); // 原有Action方法不变 public override State Action1() => new StateA(_entity); public override State Action2() => null; public override State Action3() => null; } public class StateA : State { public StateA(Entity entity) : base(entity) { } public override (Type, string)? NextHappyState => (typeof(StateB), nameof(Action2)); public override State Action1() => null; public override State Action2() => new StateB(_entity); public override State Action3() => new StartState(_entity); } public class StateB : State { public StateB(Entity entity) : base(entity) { } public override (Type, string)? NextHappyState => (typeof(EndState), nameof(Action1)); public override State Action1() => new EndState(_entity); public override State Action2() => null; public override State Action3() => new StartState(_entity); } public class EndState : State { public EndState(Entity entity) : base(entity) { } public override (Type, string)? NextHappyState => null; public override State Action1() => null; public override State Action2() => null; public override State Action3() => null; }
遍历获取完整路径:
public static List<(Type StateType, string ActionToNext)> GetStaticHappyPath(Entity entity) { var path = new List<(Type, string)>(); var currentStateType = typeof(StartState); while (true) { var tempState = (State)Activator.CreateInstance(currentStateType, entity); path.Add((currentStateType, tempState.NextHappyState?.ActionName)); var nextState = tempState.NextHappyState; if (nextState == null) break; currentStateType = nextState.Value.NextStateType; } return path; }
方案2:集中式静态配置
如果希望路径统一管理,创建静态配置类:
public static class HappyPathConfig { public static readonly List<(Type CurrentState, string Action, Type NextState)> Path = new List<(Type, string, Type)>() { (typeof(StartState), nameof(State.Action1), typeof(StateA)), (typeof(StateA), nameof(State.Action2), typeof(StateB)), (typeof(StateB), nameof(State.Action1), typeof(EndState)) }; // 获取完整状态顺序 public static List<Type> GetStateSequence() { var sequence = new List<Type> { typeof(StartState) }; sequence.AddRange(Path.Select(p => p.NextState)); return sequence; } // 获取当前状态的下一个步骤 public static (string Action, Type NextState)? GetNextStep(Type currentStateType) { var step = Path.FirstOrDefault(p => p.CurrentState == currentStateType); if (step.CurrentState == null) return null; return (step.Action, step.NextState); } }
总结
- 状态转换逻辑频繁变动 → 选动态BFS方案,自动适配变化;
- 状态转换逻辑稳定 → 选静态链式标记或集中式配置,实现简单且类型安全。
内容的提问来源于stack exchange,提问作者Yoda
相关产品推荐
相关产品推荐

