游戏的架构模式

4
所以我有一个包含几个大项目的解决方案,我正在尝试将其分解为更具独立职责的小型项目。这是一个游戏,但我主要是LOB开发人员,我认为原则可能是普遍的,并且我认为我可以从中学到一些东西。
某些对象中的依赖关系有点太紧密了,我希望能得到一些帮助来解开它们。或者也许有一些模式或抽象可以使它们更易于管理。
Ares.Core.World中有像Creatures、Items等类。它们都继承自Entity,该实体知道它存在于地图上的哪个单元格中。它通过持有对Ares.Core.UI.MapControls.MapCell的引用来实现这一点...你可以看到线已经交叉了。
Ares.Core.UI.MapControls包含Map和MapCell,每个包含它们所包含的生物和物品的列表。MapCell还继承自Ares.Core.World.Entity,因为这样解决了一些早期问题非常优雅——例如,所有实体都有库存。
我想找到一种将UI和World拆分为单独项目(Ares.World和Ares.UI)的方法,因为UI和总体世界可能应该是分开的。但是,如您所见,现在两个项目需要相互引用,而循环引用是不允许的。
我想知道是否有任何架构模式可以帮助解决这种情况。谢谢!

2
你可以在programmers.stackexchange.com上得到很好的回答。 - Rick Sladkey
拥有所有内容都派生自实体的方式很好,但它会导致分离程度模糊到没有分离的地步。我认为这是第一步。我同意@Rick的观点。 - IAbstract
我通常通过创建第三个仅包含实体(模型)的项目来解决循环引用的问题,并在其中声明所有将在World和UI项目中使用的实体类。 - Dimitri
3个回答

2
因此,你的World类 - 生物、物品等等 - 都需要从MapCell获取某些内容。你能否合理地创建一个(或多个)接口来代表World实体需要什么?这样一来,实体只需要该接口的一个实现即可。
这将是解耦两者的第一步。很明显,该接口的所有方法签名或属性都不能包含UI项目中的类。它应该使用标准类型或自定义类型在World和UI都引用的库(例如Ares.Core)中进行定义。
然后,在UI项目中定义实现接口的类,该类封装了MapCell并为World实体提供所需内容。
使用您选择的IoC在需要时提供实现,具体取决于您如何获取MapCell,您可能还需要添加工厂。
没有更多关于您特定需求的详细信息,很难具体说明,但我认为这种方法通常是可行的。

谢谢,这实际上非常有帮助。那么这是“现代”编程风格最终使用接口的原因之一吗?我可以看出它如何规避循环引用的问题。 - Brian MacKay
@Brian:很高兴它有帮助。我经常使用这种模式来保持系统的部分独立、解耦和可测试性。除了避免循环引用外,它还帮助我专注于更小的单个功能块,而IoC只是让它容易地将所有东西连接起来,并在需要时获取正确的实现。 - quentin-starin

1

在不同命名空间中使用类进行细粒度交互没有任何问题。关注点的分离可以通过访问控制级别(public,protected,private等)完成。您可以将项目分解为逻辑或结构子项目,并应用您认为相关的任何额外组织约束。

一些策略可能是:

  • 结构上的分离逻辑,每个独立的沙箱都驻留在其自己建立的命名空间中,并且只通过高级接口进行交互。
  • 逻辑上的分离,其中一个程序集(或一组程序集)成为跨多个命名空间的逻辑项目。交互可以通过接口完成,也可以通过对成员访问的深入考虑来完成。

为了解开它们,请尝试从不同的角度看待项目。从某个角度看起来可能像一团糟,但从另一个角度看,实际上可能会显得简洁优雅。如果您发现他们的类结构确实有合理的逻辑,请开始将片段分离到不同的程序集中,只需要微调命名空间即可。如果您发现它真的是一团糟,好吧,那你的工作就很明确了 :-D


0
  1. 分治设计建议您将UI和核心组件分开。
  2. 游戏逻辑应该是核心模块的一部分,而不是UI。
  3. UI应该具有图形界面和操作接口或对象行为接口,并由核心模块实现。

我听说过分治算法,但没有听说过设计。这是和n层架构一样的东西吗? - Brian MacKay
规则表明,将复杂模块简化为小而简单的组件。 - Kamahire
哦,好的,这就是我所说的单一职责原则、SOLID等。谢谢 :) - Brian MacKay

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