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

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

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


当前回答

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

其他回答

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

一些代码势利者看不起他们,认为他们只是一个荣耀的全球人。就像许多人讨厌goto语句一样,也有其他人讨厌使用全局的想法。我见过几位开发人员为了避免全局性而竭尽全力,因为他们认为使用全局性是失败的承认。奇怪但真实。

在实践中,Singleton模式只是一种编程技术,它是概念工具包的有用部分。有时你可能会发现它是理想的解决方案,所以使用它。但使用它只是为了吹嘘使用设计模式,就像拒绝使用它一样愚蠢,因为它只是一个全球性的。

我不打算评论善/恶的论点,但自从春天来临以来,我就没有使用过它们。使用依赖注入几乎消除了我对单例、服务定位器和工厂的需求。我发现这是一个更加高效和干净的环境,至少对于我所做的工作类型(基于Java的web应用程序)来说是如此。

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

考虑以下情况:作为开发人员,您必须创建一个访问数据库的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应用程序的多个实例。现在,你突然有了这样的想法:

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

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

摘自Brian Button:

它们通常被用作全局实例,为什么如此糟糕?因为您将应用程序的依赖项隐藏在代码中,而不是通过接口公开它们。让一些东西全球化以避免传播是一种代码气味。他们违反了单一责任原则:因为他们控制自己的创作和生命周期。它们固有地导致代码紧密耦合。这使得在许多情况下,在测试中伪造它们相当困难。它们在应用程序的整个生命周期中携带状态。另一个对测试的打击,因为您可能会遇到一种需要订购测试的情况,这对于单元测试来说是一个很大的禁忌。为什么?因为每个单元测试都应该彼此独立。