C#游戏开发:父类引用调用子类重写方法及消除Switch语句问询
优化游戏单元管理:消除冗余Switch,优雅利用多态
看起来你已经摸到了面向对象优化的门道,你的现有方案已经很好地解决了冗余switch的问题,我来帮你把这个思路梳理得更清晰,同时补充一些细节优势:
问题复盘
你当前的痛点很典型:随着游戏单元类型增加,SpawnUnit、PerformAction里的switch语句会越来越臃肿,而且每次调用子类方法都要手动类型转换,既不优雅也容易出错。你希望把类型判断的逻辑收拢,同时让父类引用能自动触发子类的重写逻辑。
你的优化方案详解
你的思路核心是把类型转换和调度逻辑封装到基类的单一方法中,同时通过多态让子类接管方法执行,这完全符合面向对象的设计原则。
1. 重构后的基类GameUnit
public class GameUnit { public enum UnitType { FighterUnit, MageUnit, Count, } public UnitType type; public virtual void OnUnitSelected() { HighlightUnit(); } // 子类可自定义的方法执行入口,保留扩展空间 public virtual void RunMethod(Action method) { method(); } // 唯一的类型判断入口,所有子类调度都走这里 public void DoAsChild(Action method) { switch (type) { case UnitType.FighterUnit: ((FighterUnit)this).RunMethod(method); break; case UnitType.MageUnit: ((MageUnit)this).RunMethod(method); break; } } }
这里的关键是DoAsChild方法:它把原来散落在各个业务方法里的类型判断收拢到了基类,后续新增单元类型时,只需要修改这一个地方的switch,避免了代码重复。
2. 子类实现(保持简洁)
public class FighterUnit : GameUnit { public FighterUnit() { type = UnitType.FighterUnit; } public override void OnUnitSelected() { PlayFighterSound(); base.OnUnitSelected(); // 保留基类的高亮逻辑 } public void Punch() { PunchInfrontOfMe(); } public override void RunMethod(Action method) { method(); } } public class MageUnit : GameUnit { public MageUnit() { type = UnitType.MageUnit; } public override void OnUnitSelected() { PlayMageSound(); base.OnUnitSelected(); } public void CastSpell() { CreateSpellAtPosition(); } public override void RunMethod(Action method) { method(); } }
子类只需要专注于自己的业务逻辑,RunMethod给了子类扩展的空间——比如如果某个子类需要在执行方法前加一些前置检查,直接重写这个方法即可。
3. 业务调用的简化
现在调用子类方法变得非常优雅,不用再到处写switch:
// 触发单元选中逻辑 public void UnitClicked(GameUnit unit) { unit.DoAsChild(unit.OnUnitSelected); } // 执行单元专属动作 public void PerformAction(GameUnit unit) { switch (unit.type) { case GameUnit.UnitType.FighterUnit: unit.DoAsChild(((FighterUnit)unit).Punch); break; case GameUnit.UnitType.MageUnit: unit.DoAsChild(((MageUnit)unit).CastSpell); break; } }
额外进阶优化建议
如果想彻底消除所有switch,可以结合工厂模式+字典映射:
- 在
GameUnitController里维护一个Dictionary<UnitType, Func<GameUnit>>,用来创建不同类型的单元,替代SpawnUnit里的switch; - 同时维护一个
Dictionary<UnitType, Action<GameUnit>>,把每个单元的专属动作映射进去,这样PerformAction里的switch也可以去掉。
不过你的现有方案已经是非常轻量化的改进,完全能解决当前的问题,适合中小规模的游戏单元系统。
内容的提问来源于stack exchange,提问作者AS_Dev
相关产品推荐
相关产品推荐

