扩展方法-C#关于为了可读性而扩展大型类

本文关键字:扩展 可读性 大型 方法 -C# | 更新日期: 2023-09-27 17:57:36

我有一个大型抽象类,用于处理游戏中的武器。通过基本功能列表进行战斗循环:

OnBeforeSwing
OnSwing
OnHit || OnMiss

我想的是将所有与战斗伤害相关的计算转移到另一个文件夹中。战斗伤害相关计算。

我想知道将OnHit方法作为扩展方法是否正确,或者实现这一点的最佳方法是什么。

此外。OnHit代码的某些部分会定期被修改,命中伤害公式很大,因为它考虑了很多条件,如阻力、转化法术、物品奖励、特殊属性和其他类似的游戏元素。

最后是一个500行的OnHit函数,这让我有点害怕。即使有区域指令,也很难在不迷路甚至分散注意力的情况下完成它。

如果我用这个功能扩展武器,而不仅仅是OnHit功能,我可以尝试将攻击的不同部分划分为其他功能。

再说一遍,也许我可以通过在武器类的OnHit中调用类似CombatSystem.HandleWeaponHit的东西来实现这一点,而不使用扩展方法。这可能更合适。

基本上,我的问题是,这样做是否真的是最好的解决方案,或者我是否可以(应该?)将这部分代码移动到一个扩展方法或一个单独的帮助程序类中,以处理损坏模型,以及我是否应该尝试将函数拆分为更小的"任务"函数,以提高可读性。

扩展方法-C#关于为了可读性而扩展大型类

我要冒险指出,您的引擎可能不够抽象。请注意,除了你在OP.中告诉我的之外,我在不了解你的系统的情况下提出了这个建议

在我设计的类似系统中,有Actions和Effects。这些都是基类。每一个特定的动作(机关枪攻击、特定的咒语等等)都是从动作衍生出来的一个类。行动有一个可以应用于目标的一个或多个具体效果的列表。这是使用依赖注入实现的。

战斗引擎本身并没有计算所有的数学。从本质上讲,它要求目标计算其防御等级,然后循环所有活动动作,并要求他们确定其效果是否适用于目标。如果他们申请,它要求行动将其相关影响应用于目标。

因此,战斗引擎很小,每个效果都很小,而且易于维护。

如果你的系统是一个巨大的整体结构,你可能会考虑类似的架构。

对于初学者来说,OnHit应该是一个事件处理程序。任何被命中的对象都应该引发一个hit事件,然后可以有一个或多个与该事件关联的事件处理程序。

如果不能将当前的OnHit函数拆分为多个事件处理程序,可以将其拆分为单个事件处理程序但将其重构为多个较小的方法,每个方法都执行特定的测试或特定的计算。它将使您的代码更加可读和可维护。

IMHO Mike Hofer提供线索。

真正的问题不在于它是否是一个扩展方法的问题。真正的问题是,对于这样一组复杂的计算来说,谈论单一(扩展或正则)方法是不可能的。

在考虑最佳实现之前,您显然需要重新思考整个事情,以确定对象上责任的最佳分配。每个元素计算都必须由它所应用的对象来完成。请始终记住GRASP设计模式,特别是Information ExpertLow CouplingHigh Cohesion

通常,项目中的每个方法都应该只有几行代码长,而不是更多。对于每一项计算,考虑一下该计算适用的所有类别。然后将这种计算方法作为它们的公共基类的一种方法。

如果没有公共基类,请创建一个新接口,并使所有这些类实现该接口。接口可能有方法,也可能没有:它可以作为一个简单的标记来识别提到的类,并使它们有一些共同点。

然后你可以构建一个基本的扩展方法,比如这个假例子:

public interface IExploding { int ExplosionRadius { get; } }
public class Grenade : IExploding { public int ExplosionRadius { get { return 30; } } ... }
public class StinkBomb : IExploding { public int ExplosionRadius { get { return 10; } } ... }
public static class Extensions
{
    public static int Damages(this IExploding explosingObject)
    {
        return explosingObject.ExplosionRadius*100;
    }
}

这个示例很俗气,但只是为了以一种更抽象、更可维护的方式重新设计您的系统。

希望这对你有帮助!