【发布时间】:2013-06-08 22:36:42
【问题描述】:
我的游戏有很多子系统。他们可以互相使用。早些时候,我正在初始化子系统引用并将其存储到静态 Game 对象中,而不是制作单例。现在我看到 Game 对其他类的引用太多,看起来很混乱:
public static PlayerSettings PlayerSettings { get { return _playerSettings; } }
public static CommunityClient Community { get; private set; }
public static DatabaseConnectionWrapper Database { get; set; }
public static LoginConnectionWrapper LoginProtocolConnection { get; set; }
public static WorldEmulatorConnection WorldEmulatorConnection { get; set; }
public static WorldPlayerConnection WorldPlayerConnection { get; set; }
public static WorldConnection WorldConnection { get { return IsEmulatorMode ? (WorldConnection)WorldEmulatorConnection : WorldPlayerConnection; } }
public static MusicManager MusicManager { get; private set; }
public static SkyboxManager SkyboxManager { get; private set; }
public static VKInfo VK { get; private set; }
我该怎么办?我不需要这些子系统的抽象。而且我认为单例并不适合这种情况 - 架构看起来被分割成碎片。我想从一个地方以正确的顺序初始化我的所有子系统。但是引用的类太多了……
添加
查看 DI - 我可以将依赖项发送到类构造函数并初始化静态工厂中的每个类。这就是我要找的。
但我刚刚意识到我的问题是,当我尝试使用 Unity3D 对象组件架构时,我无法将依赖项发送到构造函数,因为类初始化是从 UnityEngine 调用的。
所以在这种情况下,我需要 Singleton 或 Blob 来保留引用。如果我抛弃 Unity 架构,那么我将从构造函数获取所有依赖项,并且不需要单例或 blob。
我需要重新设计我的架构,UnityEngine 不会创建需要获取子系统引用的对象,而是从我的代码中创建这些类并让他们创建和管理他们的 UnityEngine“游戏对象”。
【问题讨论】:
-
这也称为
The Blob- 请参阅sourcemaking.com/antipatterns/the-blob。一个可能的选择是考虑你的班级在做什么;你可以有一个带有播放器、社区和登录设置的PlayerManager,一个带有所有世界类的WorldManager,以及一个带有相关类的EnvironmentManager。这些中的每一个都将您的问题分解为更易于管理的块。然后您也可以开始执行 SRP - en.wikipedia.org/wiki/Single_responsibility_principle -
我很想知道您为什么认为它引用了“太多的类”?从您的描述来看,这似乎是对您所描述的问题的合理解决方案 - 以正确的顺序初始化。下一个最好的方法是将每个子系统解耦到每个子系统可以独立编译和运行的程度,这也有利于使测试更容易:)
-
依赖注入是通常的解决方案,但你已经拒绝了。问题不在于上帝,而在于您在代码中调用他的名字的频率。当你有这么多全局变量时,可能会很多。所以也许你不应该拒绝 DI。
-
@HansPassant,你把我搞砸了!我告诉你。现在,就您而言,Vlad,为什么不听从 Hans 所说的,让您的生活更轻松一些,然后使用像 Unity 这样的 DI 容器来初始化 和 恢复这些对象。看,使用容器,您不需要逐字编写代码来传递所有依赖项,容器会为您完成这些,它甚至可以自己处理自定义初始化和单例。
-
哪里提到了弗拉德对 DI 的厌恶?他在宽限期内把它删掉了吗?
标签: c# design-patterns singleton god-object