各类拥有独立状态类型时,如何实现状态变更通知?
问题描述
我有多个类,每个类都有自己的状态类型。需要让知晓所有对象类型的消费者接收每个对象的状态变更通知并做出对应处理。
我当前的解决方案是创建一个包含事件的接口IProcess,每个类都实现该接口,消费者根据事件传入的ProcessType参数进行类型转换。
这个方案能正常运行,但每次新增流程时都要写大量重复代码,比如实现新的ProcessEventArgsX、在HandleStatus方法中添加新的判断分支等,所以我觉得这不是最优解。
请问有没有遗漏的设计模式,或者更优的解决方案?
当前实现代码
class ProcessA : IProcess { enum StatusA { ... } class ProcessEventArgsA : EventArgs { public StatusA Status { get; set; } } } class ProcessB : IProcess { enum StatusB { ... } class ProcessEventArgsB : EventArgs { public StatusB Status { get; set; } } } class ProcessX : IProcess { ... } interface IProcess { event Action<ProcessType, EventArgs> StatusChanged; } // Consumer List<IProcess> _processes; void Subscribe() { foreach(var proc in _processes) { proc.StatusChanged += HandleStatus; } } void HandleStatus(ProcessType processType, EventArgs e) { if(processType == ProcessType.A) { var args = e as ProcessEventArgsA; StatusA status = args.Status; DoSomethingBasedOnStatusFromProcessA(status); } else if(processType == ProcessType.B) {} ... }
优化方案
1. 泛型接口+泛型事件
通过泛型接口消除重复的EventArgs子类定义,让事件直接传递具体状态类型,避免类型转换:
// 泛型核心接口 interface IProcess<TStatus> { event Action<TStatus> StatusChanged; ProcessType ProcessType { get; } } // ProcessA实现 class ProcessA : IProcess<ProcessA.StatusA> { public enum StatusA { Idle, Running, Completed } public ProcessType ProcessType => ProcessType.A; public event Action<StatusA> StatusChanged; // 触发状态变更示例 private void OnStatusChanged(StatusA status) { StatusChanged?.Invoke(status); } } // 消费者订阅与处理 List<object> _processes; void Subscribe() { foreach (var proc in _processes) { if (proc is IProcess<ProcessA.StatusA> procA) { procA.StatusChanged += HandleProcessAStatus; } else if (proc is IProcess<ProcessB.StatusB> procB) { procB.StatusChanged += HandleProcessBStatus; } // 新增流程时仅需添加对应分支 } } void HandleProcessAStatus(ProcessA.StatusA status) { DoSomethingBasedOnStatusFromProcessA(status); } void HandleProcessBStatus(ProcessB.StatusB status) { DoSomethingBasedOnStatusFromProcessB(status); }
2. 访问者模式
将状态处理逻辑集中在访问者类中,适合需要统一管理所有流程状态处理的场景:
// 访问者接口 interface IProcessVisitor { void Visit(ProcessA process, ProcessA.StatusA status); void Visit(ProcessB process, ProcessB.StatusB status); // 新增流程时添加对应Visit方法 } // 流程基础接口 interface IProcess { void Accept(IProcessVisitor visitor); } class ProcessA : IProcess { public enum StatusA { Idle, Running, Completed } private StatusA _currentStatus; public void Accept(IProcessVisitor visitor) { visitor.Visit(this, _currentStatus); } // 触发状态变更时调用Accept通知访问者 } // 消费者实现访问者 class ProcessStatusHandler : IProcessVisitor { public void Visit(ProcessA process, ProcessA.StatusA status) { DoSomethingBasedOnStatusFromProcessA(status); } public void Visit(ProcessB process, ProcessB.StatusB status) { DoSomethingBasedOnStatusFromProcessB(status); } } // 消费者处理逻辑 void HandleAllProcessStatus() { var handler = new ProcessStatusHandler(); foreach (var proc in _processes) { proc.Accept(handler); } }
3. 动态类型+委托字典
利用C#动态类型简化类型转换,用字典存储流程类型与处理逻辑的映射:
// 修改后的IProcess接口 interface IProcess { event Action<ProcessType, dynamic> StatusChanged; ProcessType ProcessType { get; } } class ProcessA : IProcess { public enum StatusA { Idle, Running, Completed } public ProcessType ProcessType => ProcessType.A; public event Action<ProcessType, dynamic> StatusChanged; private void OnStatusChanged(StatusA status) { StatusChanged?.Invoke(ProcessType.A, status); } } // 消费者逻辑 Dictionary<ProcessType, Action<dynamic>> _statusHandlers = new() { { ProcessType.A, status => DoSomethingBasedOnStatusFromProcessA((ProcessA.StatusA)status) }, { ProcessType.B, status => DoSomethingBasedOnStatusFromProcessB((ProcessB.StatusB)status) } }; void Subscribe() { foreach (var proc in _processes) { proc.StatusChanged += (type, status) => _statusHandlers[type](status); } }
内容的提问来源于stack exchange,提问作者theateist
相关产品推荐
相关产品推荐

