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

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

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


当前回答

单身汉还不错。只有当你做了一些全球独一无二的东西而不是全球独一无二的时候,才是糟糕的。

然而,有“应用程序范围服务”(想想让组件交互的消息传递系统)-这是一个单例调用,一个“MessageQueue”-类,它有一个方法“SendMessage(…)”。

然后,您可以在各地执行以下操作:

MessageQueue.Current.SendMessage(新邮件到达消息(…));

当然,还要做到:

MessageQueue.Current.RegisterReceiver(this);

在实现IMessageReceiver的类中。

其他回答

在我的头顶上:

它们加强了紧密耦合。如果您的单例驻留在与其用户不同的程序集上,那么如果没有包含单例的程序集,using程序集就永远无法运行。它们允许循环依赖,例如,程序集A可以有一个依赖于程序集B的单例,而程序集B可以使用程序集A的单例。所有这些都不会破坏编译器。

Vince Huston有这些标准,在我看来很合理:

只有满足以下三个标准时,才应考虑Singleton:无法合理分配单个实例的所有权需要延迟初始化未提供全局访问如果单个实例的所有权、初始化发生的时间和方式以及全局访问都不是问题,那么Singleton就不够有趣了。

作者的一些对位词:

如果你将来需要让班级不再单身,你就会陷入困境一点也不——我当时使用的是一个数据库连接单例,我想将其转换为一个连接池。请记住,每个单例都是通过标准方法访问的:

我的类别实例

这类似于工厂方法的签名。我所做的只是更新实例方法以返回池中的下一个连接,无需进行其他更改。如果我们没有使用单例的话,那就更难了。

单身汉只是花式的全球明星这一点无可厚非,但所有静态字段和方法也是如此——从类而不是实例访问的任何东西本质上都是全局的,我看不出静态字段的使用有多大阻碍?

并不是说单身汉很好,只是反驳了这里的一些“传统智慧”。

摘自Brian Button:

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

Chris Reath最近在《无注释编码》杂志上发表的关于此主题的文章。

注意:无注释编码不再有效。但是,链接到的文章已被其他用户克隆。

Link