为什么Singleton被认为是反模式?

use*_*031 71 design-patterns anti-patterns

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

单身人士设计模式:陷阱

单身反模式

我最近听说过Singleton是一种反模式.我知道它与事实有关,使得一个类单例就像使该唯一实例成为一个全局变量,但它也做了很多(限制该对象的实例数,管理实例化等等).

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

Jam*_*ack 67

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

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

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

有关这方面的更多信息,请访问:https://www.michaelsafyan.com/tech/design/patterns/singleton

以下是上述博客的一个很好的结局:

简而言之,单例模式使代码更复杂,更有用,并且重新使用或测试真正的痛苦.消除单身人士可能很棘手,但这是值得的努力.

好吧,因此,它是一个反模式的原因在本段中有很好的描述,并且正如作者所表达的那样,它将你的代码紧密地耦合到单例.

如果您发现要使用单件,可能需要考虑您的设计,但有时候它会有用.

例如,一旦我必须编写一个最多只能有一个数据库连接的应用程序,就可以处理数千个请求.因此,单身人士是有道理的,因为我资源限制只有一个实例.

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

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

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

如果您发现仍然需要它,那么请使用它,但要意识到以后会遇到的问题.

  • 好答案.只是想补充说,即使你的数据库示例也应该用单身人士来解决.最简单的解决方案,明确地知道确切的用例,就是拥有一个返回单个实例的工厂.这是一种更优雅的方法,并且不违反SRP(正如Singleton模式那样).此外,如果情况发生变化并且您的应用程序需要修改以允许多个数据库连接,那么与单例相比,重构将是轻而易举的.从字面上看,不存在单身人士优于另一种模式的情况. (4认同)
  • @Creynders - 实际上我的问题是通过运行一个单独的程序来解决的,该程序只是查看队列并处理它发现的内容,所以它只有一个连接,但是,单例可能很适合那里。我遇到了类似的问题,我可能只允许 5 个连接,并且类似于单例的东西可能会起作用,因为它基本上是一个功能类似于单例的工厂。 (2认同)
  • 数据库是反模式的一个很好的例子——围绕当前的性能假设构建整个程序逻辑。 (2认同)

Jac*_*nds 20

我不会完全认为单身是一种反模式.

但是,单例基本上是一种使用全局变量的方法.全局变量很糟糕,因为系统中任何地方的任何代码都可以改变它们的值.因此,在调试时,可能很难确定哪个代码路径导致单例的当前状态.

  • 错误的。如果全局变量被隐藏,则无法更改。 (3认同)
  • 原因不是这个。Singleton 做了 3 件事(违反单一职责原则):它履行其主要职责,它是一个工厂(参见工厂模式),它确保单个实例(这是一个坏主意,除非它是临时措施,以标记一个实例)。类需要重复,因此可以有多个实例)。 (2认同)

pet*_*nto 10

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

我同意您的看法,Singleton可以作为全球唯一的实例.我从一些人那里了解到,作为Singleton的替代品,我们可以使用静态和/或最终变量,我们也可以使用枚举(这样我们就可以将多个变量分组在一个组名下,就像我们在使用普通类/对象).

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

干杯...... :))


dan*_*iel 6

单身人士经常被严重执行.请参阅双重检查锁定.

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

单身人士很难测试.

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

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

  • "分配给Singleton的内存无法释放." 也许那个记忆不需要被释放,这就是它被放入Singleton的原因?另外,如果需要,它可以释放内存. (8认同)