我应该为消息接收器创建接口吗

本文关键字:接口 创建 接收器 消息 我应该 | 更新日期: 2023-09-27 18:26:57

在我使用的游戏引擎(Unity)中,每个游戏对象的基类都有一个方法"SendMessage("methodName")",它调用与它相关联的每个对象的每个类中的指定方法(如果有)。

我应该用方法"methodName"为我可以通过这种方式发送的每一条消息创建一个新的接口来形式化这种交互吗?还是这只是额外的工作而没有任何收获?这似乎是一件好事,因为这样我就可以看到这个类可以从它的声明中接收到什么消息,但我看不到有什么错误,例如,我可以帮助避免这些错误。我也没有看到它被这样使用——所以这可能只是一种浪费。

我应该为消息接收器创建接口吗

严格回答:是,使用接口!现实生活中的答案:这可能取决于情况。通常,以这种方式使用字符串是危险的(如果方法声明会更改怎么办?如果您以错误的方式键入方法名称怎么办?您对此有任何安全问题吗?)。这些问题的答案总是:你会在运行时而不是编译时发现这些问题(这意味着你可能会发布一些不起作用的东西,即使这是一种应该在编译时发现的错误)。此外,不要忘记性能,使用字符串必须使用反射(我想/希望您不会有大的switch/case语句)。编写接口是乏味的,但99%的时候是保持代码整洁和易于维护的最佳方式。也就是说,您可能需要使用这些字符串来调用方法(例如,我正在考虑Java代理或基于配置或消息内容的某种"动态"实例化)。所以我想正确的答案是IT DEPENDS。由于速度、错误检查、维护和安全问题(如适用),我认为您应该始终使用接口。有时你可能需要使用文本消息,但你应该小心使用它们,永远不要因为你会写更少的代码(这从来都不是选择一种方法而不是另一种方法的好理由)。

附录:对于接口,您可以使用"服务守护进程"机制(例如基于IServiceProvider)来发现实现特定接口的所有对象。使用SendMessage()实现同样的事情可能很棘手(你会使用CanHandlMessage()方法吗?)并且由于重复而容易出错。

示例:这只是一个例子(为了解释我对"服务守护进程"的意思,请参阅函数FindServices(),它检索实现给定接口的所有对象),我想你不会在高速游戏中使用LINQ和枚举。我认为它比带参数的SendMessage()更容易理解,而且更新也很容易。

interface IEnemy
{
 Point3D Position
 {
  get;
  set;
 }
 void Destroy();
}
void FireBomb(Bomb bomb, Point3D impactLocation)
{
 IEnumerable<IEnemy> affectedEnemies = 
  FindServices<IEnemy>.Where(x.Location - impactLocation <= bomb.BlastedArea);
 Execute(affectedEnemies, x => x.Destroy());
}

我应该使用接口而不是接受字符串并调用函数的方法吗?

优点:

  • 编译时间安全。(耶!)
  • 比反思更快(查看这是否是合法的胜利)

缺点:

  • 需要编写更多代码

请随意在.中编辑更多优点/缺点

我肯定会查找具有所需接口(GetComponent<IInterface>GetComponent(typeof(IInterface)) as IInterface)的组件,并以这种方式调用方法(即接口)。

如果定义接口IGolerkaEventHandler<T> {bool InvokeHandler(T param);},则可以有一个方法HandleGolerkaEvent<TT>(TT param),该方法遍历WeakReference的列表,尝试将每个的目标强制转换为IGolerkaEventHandler<TT>,并在执行强制转换的每个方法上调用InvokeHandler(param)。这将允许(要求)不同的"事件"类型接受不同的参数类型。在接口中将T定义为in参数可能是有利的,也可能不是有利的,这取决于您是否希望有多个事件,这些事件对于某些对象可以由公共代码处理,而对于其他对象可能需要不同的处理。