目前我对这种“设计模式”非常感兴趣。我不确定是否有使用这种严格的全局状态实施的垮台。那么,你认为什么时候不在应用程序中练习单身?
答案 0 :(得分:37)
如果您正在进行单元测试,单身通常是一个坏主意,而且不进行单元测试(或BDD或验收测试)通常是一个坏主意。
使对象具有全局状态意味着您编写的涉及这些对象的单元测试将被隔离并且彼此不相交。相反,你将不得不担心重置每个测试的状态,并相信我......这种情况从未100%完成。如果你没有重置全局状态,那么你开始变得非常奇怪并且很难在你的测试中调试浪费时间的错误。
全局状态也会增加代码中的耦合并使其很难重构。
理想的方法是使用IoC / DI容器(Spring,Guice等)来请求对象。这些容器通常有使对象显示为“单身人士”的方法,但他们也有办法根据情况修改该行为(即单元测试与域代码)。
这一切都取决于你问题的大小。如果你正在组织一个4级试验台试试看,那就继续使用Singleton。然而,只要该项目具有生命并且变得更大,更复杂,那么重构单身人士。
答案 1 :(得分:19)
谷歌技术会谈前段时间有关于Global State and Singletons的精彩演讲。静态单例模式是邪恶的,因为它会导致不必要的副作用并使代码不可测试。静态单例是全局变量的OO版本。
解决方案是只创建对象的一个实例并通过依赖注入将其传递给用户。 DI框架,例如Guice,可以很容易地定义好的单例(在Guice中只用@Singleton注释一个类)。有一个名为Don't Look For Things!的类似技术讲座,更多地讨论了DI。
答案 2 :(得分:7)
除了其他帖子中提到的测试和设计问题,单身人士和类加载器也存在问题。单身者并不是每个JVM或应用程序真正“单一” - 他们通过静态属性实现这一点,这实际上意味着每个类都有一个。如果有多个类加载器 - 就像在大多数应用服务器中一样 - 每个单独的应用程序都会获得一个新的类加载器,甚至在EJB中使用多级类加载器。每个类加载器加载一个单例实例 - 这取决于你对单例执行的操作,可能无法产生预期的结果。
答案 3 :(得分:3)
我很少使用Singleton。由于它们的性质(静态,全局对象),它们很难用于单元测试代码。您最终需要进行一些同步或构建一些重新初始化机制,以便您可以为每个单元测试获得一个新版本。有些情况是有意义的 - 例如,全球配置类 - 但它们比单身人士似乎相信的人要少得多。我知道我经历了一个阶段,在那里我看到了单例模式的应用。现在我尽可能地避免它,并通过在我的代码中重构来解除它,因为我遇到了不必要的实现。