如果“ ResourceManager”类被认为是不好的,那有什么替代方法?


19

我听到有相互矛盾的意见,例如:

  • “专用的Manager类几乎永远不是正确的工程工具”
  • “(目前)专用的Manager类是在拥有数千个资源的大型项目中生存的最佳方法”

让我们来看一个经典的ResourceManager类,它具有以下功能:

  • 加载资产(纹理,音频,3D模型等)
  • 通过保留缓存确保资产仅加载一次
  • 引用计数资产以确定是否可以将其释放
  • 隐藏实际资产的来源(例如,每个资产一个文件,或一个包文件中的所有资产,或者甚至可以通过网络加载资产)
  • 可以在不重新启动程序的情况下重新加载资产,这对于从事游戏的美术师来说非常有用。

假装这些ResourceManager对象不是单例,而是通过依赖项注入传递它们,让我们从表中删除“ singletons is bad”参数

然后是“使用工厂”或“称其为工厂”参数。我的问题是,是的,它是一个工厂,但它也是一个缓存和一个重装器(因为缺少更好的词)。称其为工厂并不能正确地描述它,如果我将其设置为合适的工厂,那么在哪里实现缓存和重新加载呢?

我同意“经理”类通常是不良体系结构的征兆,但是在这种特殊情况下,如何对其进行重组并仍然保留所有功能?这是“经理”类实际上合适的情况吗?


3
也许称它为仓库而不是工厂?:P
deceleratedcaviar

Answers:


9

我认为问题不在于这是一个不好的设计。问题是名称“ Manager”是无法描述的,例如“ Update”,“ Process”和“ Actor”。这对尝试理解此系统的人没有帮助,并且如果您有其他对资产执行某些操作的类,则会造成混乱。

但是,以一种有效地传达其目的的方式来命名事物确实非常困难。大多数系统过于复杂,以致于无法通过名称来显示。您能做的最好的事情就是尝试缩小使该类成为一类的凝聚力以及哪些其他类需要明显区别的特定概念,并选择一个合适的词。

恕我直言,好名最重要的特征是,它在人们看到的上下文中(代码库)是唯一的,并且易于记忆。测试应该是您是否可以与熟悉代码的队友进行对话,而不必弄清您要指的是什么。如果您需要编写参考文档,这也将有所帮助。

最后,请考虑一下,如果您无法描述这种内聚的想法,那么它可能就不会非常内聚。例如,您可以在AssetCache中分离缓存和引用计数,然后将加载保留在AssetLoader中。但这确实取决于代码的复杂程度和相互联系。

但是,如果您的AssetManager具有足够的凝聚力,而您的游戏中没有其他资产是AssetManagery,那么它可能就是一个很好的名字。


AssetLoader / AssetCache分离不是一个坏主意。
Tom Dalling

4

“我是在一个地方做到这一点,还是在很多地方做到这一点?”

加载逻辑通常集中在单个访问点上,因为它倾向于仅在应用程序中的关键点运行,而在这些关键点上,我们正试图尽快解决它。这通常发生在应用程序启动,游戏级别启动或玩家位置要求加载新块以保持无缝体验的情况下。考虑到这是作为一个批处理过程完成的(无论是一个大块还是许多较小的块都没有关系),所以有一个方法或一组方法可以调用以启动该过程是有意义的。

在大多数平台上,加载是异步的,因此您实际上别无选择,只能将加载的代码流与其他应用程序逻辑分开,这是将资源管理功能抽象到自己的类中的另一个原因。

最后,需要考虑以下几点:

与例如相比,资源加载不是经常运行。游戏逻辑,是否值得为此增加单个游戏对象的复杂性?通常,游戏对象要保持尽可能轻,并且仅用于模拟过程中需要的对象。

如果一个对象负责它自己的创造和毁灭?这可能在实体管理期间引起严重的头痛。如果您希望某个对象执行其自己的创建过程(包括获取资源依赖项),那么它也将具有销毁自身的责任。这可能导致悬空/空指针,因此实际上必须从外部进行管理。请参阅答案,以更详细地概述该问题。


PS除了通常的“单子很糟糕”类型的参数(这是非常教条的)之外,您是否见过反对ResourceManagers的好方法?对于这种特定情况, “专用Manager类几乎永远不是正确的工程工具” 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.