96

可能的重复:
单身人士有什么不好的?

单例设计模式:陷阱

单例反模式

我最近听说 Singleton 是一种反模式。我知道这与创建一个类单例就像使该唯一实例成为全局变量这一事实有关,但它的作用远不止于此(限制该对象的实例数量,管理实例化等)。

为什么 Singleton 被认为是反模式?还有哪些选择?

4

4 回答 4

85

为了帮助回答,这里有更多关于反模式评论的信息:

它被过度使用,在实际不需要类的唯一实例的情况下引入了不必要的限制,并将全局状态引入应用程序

来自:http ://en.wikipedia.org/wiki/Singleton_pattern

有关这方面的更多信息,您可以查看:https ://www.michaelsafyan.com/tech/design/patterns/singleton

这是上面博客的一个很好的结局:

简而言之,单例模式使代码更复杂、更没用,并且重用或测试非常痛苦。消除单例可能很棘手,但这是一项值得的努力。

好的,所以,本段很好地描述了它是反模式的原因,并且正如作者所说,它将您的代码与单例紧密耦合。

如果您发现要使用单例,您可能需要考虑您的设计,但有时它很有用。

例如,曾经我必须编写一个最多可以有一个数据库连接的应用程序来处理数千个请求。因此,单例是有意义的,因为我的资源受限于只有一个实例。

但是,这通常用于简化代码,而不考虑将引入的困难。

例如,这也适用于静态类,如果您进行单元测试或具有并发性,那么一个请求的状态将改变状态,这可能会导致问题,因为调用实例的类可能会假设状态与它一样预期的。

我认为挑战使用的最好方法是考虑如果您的程序是多线程的,如何处理它,而一种简单的方法是对它进行单元测试,如果您同时运行多个测试。

如果你发现还需要它,那就用它,但要意识到后面会遇到的问题。

于 2012-10-06T00:22:43.870 回答
29

我不会完全认为单例是一种反模式。

但是,单例基本上是一种使用全局变量的方法。全局变量很糟糕,因为系统中任何地方的任何代码都可以更改它们的值。因此,在调试时,找出导致单例当前状态的代码路径可能具有挑战性。

于 2012-10-06T00:14:59.133 回答
9

单例通常执行不力。请参阅双重检查锁定。

Singleton 实例在哪个范围内必须是唯一的。像多线程环境,集群等。

单例可能很难测试。

分配给 Singleton 的内存无法释放。

随着单例的过度使用,您将从面向对象编程转向过程编程。

于 2012-10-06T00:24:19.213 回答
9

我认为它被认为是一种反模式,因为 Singleton 类不能由其他对象以正常方式实例化(除非通过调用通常称为“getInstance”的方法)。因此,看起来该类被直接使用,而无需先实例化它来创建可用对象。

我同意你的观点,Singleton 可以作为一个全局唯一实例。我从一些人那里了解到,作为 Singleton 的替代方案,我们可以使用静态和/或最终变量,我们还可以使用枚举(这样我们就可以将多个变量分组到一个组名下,就像我们在使用普通类/对象)。

但是,这些替代方案只能与 Singleton 类在存储状态/值方面的能力相匹配。如果我们需要使用独特的函数,那些静态/最终变量和枚举将无济于事。在我看来,这就是我们需要使用单例类的情况(当我们需要一些独特的函数来处理静态/最终状态/值时)。

干杯... :))

于 2012-10-06T00:38:21.797 回答