依赖注入链式调用是一种反模式吗?

4

这里有一个问题,假设我们正在制作一款视频游戏,并希望使用依赖注入。以下是我们的情况:

Game Class  // This is just the code to keep track of the overall game logic
Character Class // This would be the guys in the game, good and bad guys both
Weapon Class // The weapons for the characters

通常情况下,当我进行依赖注入时,我会将地图上的当前位置和游戏状态注入到角色中,这样我的角色就有了知道如何创建自身等信息。然后,我让角色创建武器并注入武器强度等值以及来自Game类的其他通用游戏状态。
对我来说,这几乎像是一种反模式。我之所以这么说是因为现在你有(至少在我看来是这样)非常脆弱且难以更改的代码。如果我们想要更改传递的游戏状态信息,我们必须更改所有三个类。我们首先对Game类进行原始更改,然后修改Character类,最后还要修改Weapon类。如果您需要深入5层而不仅仅是3层,那么这将是很多工作量。尽管使用依赖注入比不使用更容易进行单元测试。
这似乎又是一种不好的实践方式。这是通常的做法吗?如果我们有一种“MotherShip”模式,其中所有内容都处于顶层,会怎样呢?因此,我们可以让游戏类(或其他类)创建所有内容,而不是让游戏创建角色创建武器。
这样,如果我们想要为角色添加新武器,游戏类可以直接创建并注入武器。对于这个问题,我们不确定该怎么做。谢谢!
2个回答

6
Chaining或嵌套依赖是一种完全自然的做法(尽管我必须同意tster的观点,你的例子听起来有点奇怪),但我认为我能理解为什么你会发现它很脆弱 - 即,如果你将具体类型注入到它们的使用者中。
诀窍在于在每个依赖层面引入一个接口,以便您可以独立地变化实现而不影响使用者。例如,您应该定义一个“IGame”接口并将其注入到“Character”类中,而不是直接注入到“Game”类中。
即便如此,具有许多深层嵌套接口的代码仍然可能很脆弱,因为您可能需要经常更改接口本身。最好尽可能遵循Hollywood PrincipleLaw of Demeter

3
设计问题很难回答,特别是当示例似乎没有意义时。在这种情况下,角色创建武器并不合理。一个角色应该只负责自己的事情。也许你可以给角色添加一把武器,但是,除非角色是武器制造商,否则我认为它不会实际创建一个新的武器类。
顺便说一句,我认为比这两个模式更好的模式是工厂模式。创建一个负责创建武器的类和一个负责创建角色的类。这样,如果有3或4个地方需要在创建角色时进行更改,那么该工厂就可以处理该行为,并且将其包含在未来的更改中。

我认为设计问题可能对你来说没有意义,因为你可能已经知道了正确的做法?这只是一个猜测。我认为我仍然被困在老派的面向对象思维中,每个类都拥有许多子类(比如世界有房子,房子有人,人有衣服等)。不过你的建议对我很有意义。我认为一个角色必须要知道他的武器,但这可能只是注入的。谢谢你关于工厂模式的提示。但我通常面临的情况只会有一个单一实例。这个例子是我最好的例子。 - Matthew Stopa
2
你需要注意的是要关注对象实际创建的位置。当你使用 "new" 关键字时,你将自己锁定在单一实现中,因此你需要控制它。此外,谁创建了一个对象就要对其负责,直到他们可以将其传递给另一个负责人。在 {House, Person, Clothes} 的例子中,类型为 Clothes 的对象应该在其他地方创建并交给 Person 或 House 对象。 - tster
好的,那就是我的问题了。我把依赖关系搞反了。前几天我在SO上发布了一个类似的问题,有很多人认为这个依赖链非常正常,所以我认为并不是每个人都知道这个问题。您是否知道任何原则或书籍,真正涉及正确的依赖关系顺序和重要实践之类的内容? - Matthew Stopa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接