如何优化含SubRequest的Request类多状态管理设计?
现有一个Request类,包含多种状态,且可关联多个SubRequest,SubRequest的状态变更会同步到Request。当前实现如下:
Request { public MyState SignatureState{get; set;} public MyState CheckedState{get; set;} public MyState ConfirmedState{get; set;} ....20 more public ICollection<SubRequest>? subs {get; set;} } SubRequest { public MyState SignatureState{get; set;} public MyState CheckedState{get; set;} public MyState ConfirmedState{get; set;} ....20 more }
SubRequest可在Request创建时或运行中添加,当SubRequest状态变更时,Request状态需同步更新。当前在Logic类中通过大量if语句处理状态检查和变更,状态由用户设置,且需前一个状态为Confirmed才能修改下一个状态。此外,存在LoanRequest、StateAidRequest等Request子类,它们不需要全部状态,目前通过switch语句在创建时将不需要的状态设为Not_Needed。现有实现繁琐冗余,曾考虑状态模式但觉得不适用,寻求更优设计方案。
补充Logic类代码:
public class Logic{ public updateState(Request req){ if(req.SignatureState==DONE) req.ChekedState=NEXT; if(req.CheckedState==DONE) req.ConfirmedState=NEXT; .... if(req.LastState==DONE) req.CompletelyDone = true; } public StateChanged(Request req){ req.CompletelyDone=false; } public resetStates(Request req){ req.SignatureState=NEXT; req.CheckedState = TO_BE_DONE; ..... } }
UI/Controller会检查状态是否为NEXT,若是则允许用户修改,否则锁定。每次SubRequest状态变更时都会调用updateStates方法。
1. 用状态组+枚举替代零散状态属性
把一组关联的状态抽象成ProcessStage枚举,每个枚举项对应一个流程阶段(比如Signature、Checked、Confirmed等),然后用字典存储每个阶段的状态,替换20多个重复的属性,同时方便扩展:
public enum ProcessStage { Signature, Checked, Confirmed, // 其他阶段 } public class RequestBase { public Dictionary<ProcessStage, MyState> StageStates { get; set; } = new(); public ICollection<SubRequest>? Subs { get; set; } public bool CompletelyDone => StageStates.Values.All(s => s == MyState.DONE); } public class SubRequest { public Dictionary<ProcessStage, MyState> StageStates { get; set; } = new(); }
对于不同的Request子类(如LoanRequest),只需在构造时初始化自身需要的ProcessStage,无需设置Not_Needed:
public class LoanRequest : RequestBase { public LoanRequest() { StageStates.Add(ProcessStage.Signature, MyState.TO_BE_DONE); StageStates.Add(ProcessStage.Checked, MyState.TO_BE_DONE); // 只添加需要的阶段 } }
2. 用规则引擎处理状态流转逻辑
把状态流转规则(比如“前一个阶段为DONE时,下一个阶段设为NEXT”)抽象成可配置的规则集合,替换Logic类中大量的if语句:
public class StateTransitionRule { public ProcessStage PreviousStage { get; set; } public ProcessStage NextStage { get; set; } public MyState TriggerState { get; set; } = MyState.DONE; public MyState TargetState { get; set; } = MyState.NEXT; }
在Logic类中维护规则列表,通过遍历规则处理状态更新:
public class Logic { private readonly List<StateTransitionRule> _transitionRules = new() { new StateTransitionRule { PreviousStage = ProcessStage.Signature, NextStage = ProcessStage.Checked }, new StateTransitionRule { PreviousStage = ProcessStage.Checked, NextStage = ProcessStage.Confirmed }, // 其他流转规则 }; public void UpdateState(RequestBase req) { foreach (var rule in _transitionRules) { if (req.StageStates.TryGetValue(rule.PreviousStage, out var prevState) && prevState == rule.TriggerState && req.StageStates.TryGetValue(rule.NextStage, out _)) { req.StageStates[rule.NextStage] = rule.TargetState; } } } public void StateChanged(RequestBase req) { req.CompletelyDone = false; } public void ResetStates(RequestBase req) { foreach (var stage in req.StageStates.Keys) { req.StageStates[stage] = stage == ProcessStage.Signature ? MyState.NEXT : MyState.TO_BE_DONE; } } }
新增状态流转时只需添加规则,无需修改大量if语句,不同Request子类也可以有独立的规则集合。
3. 让SubRequest状态变更自动同步到Request
给SubRequest添加状态变更事件,当状态改变时触发事件,Request订阅事件并自动更新自身状态,避免手动调用updateStates:
public class SubRequest { public event Action<ProcessStage, MyState> StageStateChanged; private Dictionary<ProcessStage, MyState> _stageStates = new(); public Dictionary<ProcessStage, MyState> StageStates => _stageStates; // 单个状态设置方法,触发事件 public void SetStageState(ProcessStage stage, MyState state) { _stageStates[stage] = state; StageStateChanged?.Invoke(stage, state); } }
在Request中订阅每个SubRequest的事件:
public class RequestBase { public void AddSubRequest(SubRequest sub) { Subs ??= new List<SubRequest>(); Subs.Add(sub); sub.StageStateChanged += OnSubStageStateChanged; } private void OnSubStageStateChanged(ProcessStage stage, MyState state) { // 示例逻辑:所有SubRequest该阶段都完成时,Request对应阶段设为完成 if (Subs.All(s => s.StageStates.TryGetValue(stage, out var sState) && sState == MyState.DONE)) { StageStates[stage] = MyState.DONE; new Logic().UpdateState(this); } } }
4. 用策略模式处理不同Request子类的状态逻辑
如果不同Request子类的状态流转规则差异较大,为每个子类定义对应的状态策略,解耦子类与状态逻辑:
public interface IRequestStateStrategy { void InitializeStates(RequestBase request); void UpdateStates(RequestBase request); } public class LoanRequestStateStrategy : IRequestStateStrategy { public void InitializeStates(RequestBase request) { request.StageStates.Add(ProcessStage.Signature, MyState.NEXT); request.StageStates.Add(ProcessStage.Checked, MyState.TO_BE_DONE); // 贷款请求专属初始化逻辑 } public void UpdateStates(RequestBase request) { // 贷款请求专属状态流转逻辑 } } public class StateAidRequestStateStrategy : IRequestStateStrategy { // 救助请求专属逻辑 }
在Request子类构造时注入对应的策略:
public class LoanRequest : RequestBase { public LoanRequest(IRequestStateStrategy strategy) { strategy.InitializeStates(this); } }
新增子类只需添加对应的策略类,无需修改现有代码。
内容的提问来源于stack exchange,提问作者EsoMoa

