单例模式是GoF模式书中一个完全付费的成员,但最近它似乎被开发人员世界孤立了。我仍然使用了相当多的单线程,特别是对于工厂类,虽然你必须对多线程问题(像任何类一样)小心一点,但我不明白为什么它们如此糟糕。

Stack Overflow似乎特别假设每个人都认为Singleton是邪恶的。为什么?

请用“事实、参考资料或具体专业知识”来支持您的回答


当前回答

这是我认为目前为止答案中缺少的:

如果每个进程地址空间需要一个此对象的实例(并且您尽可能确信此需求不会改变),那么应该将其设置为单例。

否则,它不是单例。

这是一个非常奇怪的要求,用户几乎不感兴趣。进程和地址空间隔离是一个实现细节。它们仅在用户希望使用kill或Task Manager停止应用程序时才会对用户产生影响。

除了构建一个缓存系统之外,没有太多的原因可以让您如此确信每个进程只应有一个实例。日志记录系统怎么样?对于每线程或更细粒度的消息可能更好,这样您可以更自动地跟踪消息的来源。应用程序的主窗口如何?这取决于;也许出于某种原因,您希望所有用户的文档都由同一进程管理,在这种情况下,该进程中会有多个“主窗口”。

其他回答

还有一件关于单身汉的事,还没有人说过。

在大多数情况下,“singletony”是某个类的实现细节,而不是其接口的特征。控制容器的反转可能会对类用户隐藏此特性;您只需要将类标记为singleton(例如,在Java中使用@singleton注释),就可以了;IoCC将完成剩下的工作。您不需要提供对单例实例的全局访问,因为访问已经由IoCC管理。因此,IoC Singleton没有任何问题。

与IoC Singleton相反的GoF Singleton应该通过getInstance()方法在接口中暴露“singletony”,因此他们会受到上面所说的一切影响。

我想谈谈公认答案中的4点,希望有人能解释我为什么错了。

为什么在代码中隐藏依赖项不好?已经有几十个隐藏的依赖项(C运行时调用、OS API调用、全局函数调用),单例依赖项很容易找到(搜索instance())。“使某个东西全局化以避免传递它是一种代码气味。”为什么不传递某个东西以避免使其成为单例代码气味?如果您通过调用堆栈中的10个函数传递一个对象,只是为了避免一个单例,那么这样做好吗?单一责任原则:我认为这有点模糊,取决于你对责任的定义。一个相关的问题是,为什么将这个特定的“责任”添加到一个班级中很重要?为什么将一个对象传递给一个类比将该对象作为类内的单例使用更紧密地耦合?为什么会改变国家的持续时间?单例对象可以手动创建或销毁,因此控件仍然存在,您可以使其生存期与非单例对象的生存期相同。

关于单元测试:

并非所有的类都需要是单位已测试并非所有需要成为单元的类测试需要更改单例的实现如果它们确实需要进行单元测试确实需要改变实施方式,很容易从使用singleton来实现通过依赖项传递给它的singleton注射

它很容易(ab)用作全局变量。依赖于单态的类相对来说更难单独进行单元测试。

单身者在集群方面也很糟糕。因为这样,您的应用程序中就不再有“恰好一个单例”了。

考虑以下情况:作为开发人员,您必须创建一个访问数据库的web应用程序。为了确保并发数据库调用不会相互冲突,您可以创建一个线程保存SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

因此,您可以确定应用程序中只存在一个singleton,并且所有数据库都通过这一个也是唯一的SingletonDao。您的生产环境现在如下所示:

到目前为止一切都很好。

现在,考虑您想在集群中设置web应用程序的多个实例。现在,你突然有了这样的想法:

这听起来很奇怪,但现在您的应用程序中有很多单例。这正是单例不应该是的:它有很多对象。如果您想对数据库进行同步调用,如本例所示,这尤其糟糕。

当然,这是单例用法错误的一个例子。但是这个例子的信息是:你不能相信你的应用程序中只有一个单例实例,特别是在集群方面。

参见Wikipedia Singleton_pattern

一些人还认为它是一种反模式,他们认为它被过度使用,在实际上不需要类的唯一实例的情况下引入了不必要的限制。[1][2][3][4]

参考文献(仅文章中的相关参考文献)

^亚历克斯·米勒。我讨厌的模式#1:辛格尔顿,2007年7月^Scott Densmore。为什么单身汉是邪恶的,2004年5月^史蒂夫·耶格。单身汉被认为愚蠢,2004年9月^J.B.Rainsberger,IBM。2001年7月,明智地使用你的单身