Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 单例设计模式:陷阱_Java_Design Patterns_Singleton - Fatal编程技术网

Java 单例设计模式:陷阱

Java 单例设计模式:陷阱,java,design-patterns,singleton,Java,Design Patterns,Singleton,目前我对这种“设计模式”非常感兴趣。不过,我不确定使用这种严格的全局状态实现是否会导致失败。那么,您认为什么时候不在应用程序中使用singleton呢?如果您正在进行单元测试,singleton通常是个坏主意,而不进行单元测试(或BDD或验收测试)通常是个坏主意 使对象具有全局状态意味着您编写的涉及这些对象的单元测试将彼此隔离和分离。相反,你将不得不担心重置每个测试的状态,相信我。。。这从来不是100%的时候都能做到的。如果不重置全局状态,那么测试中就会出现非常奇怪且难以调试的错误,这些错误会浪

目前我对这种“设计模式”非常感兴趣。不过,我不确定使用这种严格的全局状态实现是否会导致失败。那么,您认为什么时候不在应用程序中使用singleton呢?

如果您正在进行单元测试,singleton通常是个坏主意,而不进行单元测试(或BDD或验收测试)通常是个坏主意

使对象具有全局状态意味着您编写的涉及这些对象的单元测试将彼此隔离和分离。相反,你将不得不担心重置每个测试的状态,相信我。。。这从来不是100%的时候都能做到的。如果不重置全局状态,那么测试中就会出现非常奇怪且难以调试的错误,这些错误会浪费时间

全局状态还增加了代码中的耦合,使重构变得非常困难

理想的方法是使用IoC/DI容器(Spring、Guice等)来请求对象。这些容器通常有使对象显示为“单例”的方法,但它们也有根据情况修改该行为的方法(即单元测试与域代码)


这当然取决于你问题的大小。如果你正在拼凑一个4级的测试平台来尝试一些东西,那么就使用单例测试吧。然而,一旦这个项目开始运作,变得更大、更复杂,就重构出单例。

我很少使用单例。由于它们的性质(静态、全局对象),它们很难用于代码的单元测试。您最终需要进行一些同步或构建一些重新初始化机制,以便为每个单元测试获得一个新版本。有些情况是有道理的——比如说,一个全局配置类——但它们比不熟悉singleton的人所相信的要少得多。我知道我经历了一个阶段,在那个阶段我到处都能看到单例模式的应用。现在,当我遇到一个不必要的实现时,我会尽可能地避免它,并通过在代码中重构来撤销它。

除了在其他文章中提到的测试和设计问题之外,还有单例和类加载器的问题。单例并不是每个JVM或应用程序真正的“单例”——它们通过静态属性实现,这意味着每个类都有一个。如果有多个类加载器,就像在大多数应用服务器中一样,每个单独的应用程序都会得到一个新的类加载器,甚至EJB中也会使用多个级别的类加载器。每个类加载器加载一个单例实例-这取决于您对单例所做的操作,可能不会产生您期望的结果。

Google Tech Talks不久前做了一个很好的演示。静态单例模式是有害的,因为它会导致不必要的副作用,并使代码不稳定。静态单例是全局变量的OO版本


解决方案是只创建对象的一个实例,并通过依赖项注入将其传递给用户。DI框架,例如,使定义好的单例变得容易(在GUI中,只需用@Singleton注释一个类)。有一个类似的技术讲座,叫做《讨论DI更多》。

@Nate,这听起来很有趣,你能给我一个具体的例子吗?你的说法有权威的来源吗?为什么单独的JRE实例不使用单独的单例实例?@Pacerier单独的JRE使用单独的单例实例是预期的情况-问题是一个单独的JRE可以有多个类加载器,因此有多个单例实例。那么你是说单例实例永远不适合在实际项目中使用吗(在一个真实的项目中发现一个单例自动等同于代码的气味,不管用例如何)?那么不要去嗅自己。你的答案表明单例只用于“初始阶段”在所有成熟的项目中,如果项目规模越来越大,那么就应该考虑代码和代码。那么,你的意思是,单例永远不适合在这些项目中使用,还是存在有效的用例?很好。在实际项目中,单例是一种代码气味,而不管用例和项目的大小。使用DI模式(如果您愿意,使用特定的容器)完全消除对它们的需求,单例会导致解决方案更紧密地耦合,更难长期维护。这是一本关于单例是反模式的好读物。