单例模式是GoF模式书中一个完全付费的成员,但最近它似乎被开发人员世界孤立了。我仍然使用了相当多的单线程,特别是对于工厂类,虽然你必须对多线程问题(像任何类一样)小心一点,但我不明白为什么它们如此糟糕。
Stack Overflow似乎特别假设每个人都认为Singleton是邪恶的。为什么?
请用“事实、参考资料或具体专业知识”来支持您的回答
单例模式是GoF模式书中一个完全付费的成员,但最近它似乎被开发人员世界孤立了。我仍然使用了相当多的单线程,特别是对于工厂类,虽然你必须对多线程问题(像任何类一样)小心一点,但我不明白为什么它们如此糟糕。
Stack Overflow似乎特别假设每个人都认为Singleton是邪恶的。为什么?
请用“事实、参考资料或具体专业知识”来支持您的回答
当前回答
一些代码势利者看不起他们,认为他们只是一个荣耀的全球人。就像许多人讨厌goto语句一样,也有其他人讨厌使用全局的想法。我见过几位开发人员为了避免全局性而竭尽全力,因为他们认为使用全局性是失败的承认。奇怪但真实。
在实践中,Singleton模式只是一种编程技术,它是概念工具包的有用部分。有时你可能会发现它是理想的解决方案,所以使用它。但使用它只是为了吹嘘使用设计模式,就像拒绝使用它一样愚蠢,因为它只是一个全球性的。
其他回答
因为它们基本上是面向对象的全局变量,所以通常可以用这样的方式设计类,这样就不需要它们了。
作者的一些对位词:
如果你将来需要让班级不再单身,你就会陷入困境一点也不——我当时使用的是一个数据库连接单例,我想将其转换为一个连接池。请记住,每个单例都是通过标准方法访问的:
我的类别实例
这类似于工厂方法的签名。我所做的只是更新实例方法以返回池中的下一个连接,无需进行其他更改。如果我们没有使用单例的话,那就更难了。
单身汉只是花式的全球明星这一点无可厚非,但所有静态字段和方法也是如此——从类而不是实例访问的任何东西本质上都是全局的,我看不出静态字段的使用有多大阻碍?
并不是说单身汉很好,只是反驳了这里的一些“传统智慧”。
首先,一个类及其合作者应该首先实现其预期目的,而不是专注于依赖对象。生命周期管理(当实例被创建并且超出范围时)不应该是类责任的一部分。对此,公认的最佳实践是创建或配置一个新组件,以使用依赖注入来管理依赖关系。
通常,软件变得更加复杂,所以有多个状态不同的Singleton类的独立实例是有意义的。在这种情况下,提交代码来简单地抓取单例是错误的。使用Singleton.getInstance()可能适用于小型简单系统,但当需要同一类的不同实例时,它无法工作/扩展。
任何类都不应该被认为是一个单独的类,而应该是它的用法或如何使用它来配置依赖项的应用程序。对于快速而令人讨厌的应用程序来说,这并不重要——只是简单的硬编码表示文件路径不重要,但对于更大的应用程序,需要使用DI以更合适的方式分解和管理这些依赖关系。
单例在测试中引起的问题是其硬编码的单一用例/环境的症状。测试套件和许多测试都是单独的,并且是独立的,与单例硬编码不兼容。
它很容易(ab)用作全局变量。依赖于单态的类相对来说更难单独进行单元测试。
来自谷歌的Misko Hevery就这个话题发表了一些有趣的文章。。。
单身者是病态的骗子。有一个单元测试示例,说明了单身者如何难以找出依赖链并启动或测试应用程序。这是一个相当极端的虐待例子,但他提出的观点仍然有效:
单身者无非是全球国家。全局状态使您的对象可以秘密地获取未在其API中声明的内容,因此,Singleton会将您的API变成病态的骗子。
所有的Singleton都去哪儿了,这表明依赖注入使得向需要实例的构造函数提供实例变得容易,这减轻了第一篇文章中谴责的糟糕的全局Singleton背后的潜在需求。