C#中基于网络协议帧实例化子类的OOP优化方案咨询
优化方案:基于开闭原则重构对象实例化逻辑
1. 先明确基础结构
确保基类包含消息类型标识,所有子类继承基类:
public enum MessageType { TypeA, TypeB, TypeC } public abstract class ClassBase { public MessageType MsgType { get; set; } // 协议公共字段 public int CommonId { get; set; } public string CommonContent { get; set; } } public class ClassA : ClassBase { /* 类型A特有字段 */ } public class ClassB : ClassBase { /* 类型B特有字段 */ } public class ClassC : ClassBase { /* 类型C特有字段 */ }
2. 用可扩展工厂替代Switch
创建一个消息工厂,通过字典注册类型与实例化逻辑,新增子类时仅需注册,无需修改工厂核心代码:
public static class MessageFactory { private static readonly Dictionary<MessageType, Func<ClassBase, ClassBase>> _typeBuilders = new(); // 初始化已有类型的构建逻辑 static MessageFactory() { RegisterBuilder(MessageType.TypeA, baseObj => new ClassA { MsgType = baseObj.MsgType, CommonId = baseObj.CommonId, CommonContent = baseObj.CommonContent // 这里可以补充类型A特有字段的解析/赋值逻辑 }); RegisterBuilder(MessageType.TypeB, baseObj => new ClassB { MsgType = baseObj.MsgType, CommonId = baseObj.CommonId, CommonContent = baseObj.CommonContent }); RegisterBuilder(MessageType.TypeC, baseObj => new ClassC { MsgType = baseObj.MsgType, CommonId = baseObj.CommonId, CommonContent = baseObj.CommonContent }); } // 对外提供注册入口,新增子类时调用即可 public static void RegisterBuilder(MessageType msgType, Func<ClassBase, ClassBase> builder) { if (_typeBuilders.ContainsKey(msgType)) throw new InvalidOperationException($"类型{msgType}的构建逻辑已存在"); _typeBuilders[msgType] = builder; } // 核心实例化方法 public static ClassBase BuildConcreteMessage(ClassBase baseMsg) { if (_typeBuilders.TryGetValue(baseMsg.MsgType, out var builder)) return builder(baseMsg); throw new NotSupportedException($"不支持的消息类型:{baseMsg.MsgType}"); } }
3. 简化事件处理器逻辑
原来的Switch逻辑直接替换为工厂调用,新增ClassD时仅需三步:
- 给
MessageType加TypeD枚举值 - 创建
ClassD继承ClassBase - 调用
MessageFactory.RegisterBuilder注册构建逻辑
public void ProtocolRxEventHandler(byte[] frameData) { // 先解析得到仅含公共信息的基类对象 ClassBase baseMsg = ParseFrameToBase(frameData); // 工厂自动生成对应子类实例并复制公共字段 ClassBase concreteMsg = MessageFactory.BuildConcreteMessage(baseMsg); // 通知对应模块(这里如果用多态处理,扩展成本更低) DispatchToModule(concreteMsg); } // 多态分发,新增子类时仅需加一个case private void DispatchToModule(ClassBase msg) { switch (msg) { case ClassA a: ModuleA.Handle(a); break; case ClassB b: ModuleB.Handle(b); break; case ClassC c: ModuleC.Handle(c); break; // 新增ClassD时加这一行:case ClassD d: ModuleD.Handle(d); break; default: throw new NotSupportedException(); } }
4. 进阶:自动反射注册(可选)
如果不想手动写注册逻辑,可以给子类加特性,通过反射自动扫描注册:
[AttributeUsage(AttributeTargets.Class)] public class BindMessageTypeAttribute : Attribute { public MessageType TargetType { get; } public BindMessageTypeAttribute(MessageType targetType) => TargetType = targetType; } // 给子类绑定类型 [BindMessageType(MessageType.TypeA)] public class ClassA : ClassBase { } // 修改工厂静态构造函数 static MessageFactory() { // 扫描当前程序集中所有ClassBase子类 var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => t.IsSubclassOf(typeof(ClassBase)) && !t.IsAbstract); foreach (var type in types) { var attr = type.GetCustomAttribute<BindMessageTypeAttribute>(); if (attr == null) continue; _typeBuilders[attr.TargetType] = baseObj => { // 反射实例化子类 var instance = (ClassBase)Activator.CreateInstance(type); // 复制公共字段(也可以用AutoMapper简化批量复制) instance.MsgType = baseObj.MsgType; instance.CommonId = baseObj.CommonId; instance.CommonContent = baseObj.CommonContent; return instance; }; } }
这种方案下,新增子类只需要定义类+加特性,完全不需要修改原有代码,彻底实现开闭原则。
核心优势
- 新增子类时无需修改原有逻辑,仅需新增代码,符合开闭原则
- 对象创建逻辑集中管理,符合单一职责
- 后续维护、扩展成本极低
内容的提问来源于stack exchange,提问作者siii fsxa
相关产品推荐
相关产品推荐

