单例模式是GoF模式书中一个完全付费的成员,但最近它似乎被开发人员世界孤立了。我仍然使用了相当多的单线程,特别是对于工厂类,虽然你必须对多线程问题(像任何类一样)小心一点,但我不明白为什么它们如此糟糕。
Stack Overflow似乎特别假设每个人都认为Singleton是邪恶的。为什么?
请用“事实、参考资料或具体专业知识”来支持您的回答
单例模式是GoF模式书中一个完全付费的成员,但最近它似乎被开发人员世界孤立了。我仍然使用了相当多的单线程,特别是对于工厂类,虽然你必须对多线程问题(像任何类一样)小心一点,但我不明白为什么它们如此糟糕。
Stack Overflow似乎特别假设每个人都认为Singleton是邪恶的。为什么?
请用“事实、参考资料或具体专业知识”来支持您的回答
当前回答
当几个人(或团队)达成类似或相同的解决方案时,就会出现一种模式。许多人仍然使用原始形式的单件或使用工厂模板(Alexandrescu的《现代C++设计》中有很好的讨论)。并发性和管理对象生存期的困难是主要障碍,前者很容易按照您的建议进行管理。
和所有的选择一样,辛格尔顿也有其沉浮的部分。我认为它们可以适度使用,特别是对于在应用程序寿命期内仍然存在的对象。事实上,它们类似于(而且很可能是)全球性的,这可能引发了纯粹主义者。
其他回答
我不打算评论善/恶的论点,但自从春天来临以来,我就没有使用过它们。使用依赖注入几乎消除了我对单例、服务定位器和工厂的需求。我发现这是一个更加高效和干净的环境,至少对于我所做的工作类型(基于Java的web应用程序)来说是如此。
如果你使用得当且最少,单身汉并不是邪恶的。还有很多其他好的设计模式可以在某一点上替代单例的需求(也可以提供最佳结果)。但是一些程序员不知道这些好模式,在所有情况下都使用单例模式,这使得单例模式对他们来说是有害的。
单线图的一个相当糟糕的地方是,你不能很容易地扩展它们。如果你想改变他们的行为,你基本上必须构建某种装饰模式或类似的东西。此外,如果有一天你想用多种方式来做这一件事,那么改变可能会很痛苦,这取决于你如何布局代码。
需要注意的一点是,如果您确实使用了单体,请尝试将它们传递给需要它们的人,而不是让他们直接访问。。。否则,如果您选择使用多种方式来完成单例所做的事情,那么如果每个类都直接访问单例,那么很难进行更改,因为每个类都嵌入了一个依赖项。
所以基本上:
public MyConstructor(Singleton singleton) {
this.singleton = singleton;
}
而不是:
public MyConstructor() {
this.singleton = Singleton.getInstance();
}
我认为这种模式被称为依赖注入,通常被认为是一件好事。
就像任何模式一样。。。思考它,并考虑它在给定情况下的使用是否不合适。。。规则通常是被打破的,模式不应该随意应用。
Singleton不是关于单个实例!
与其他答案不同,我不想谈论Singleton有什么问题,而是想告诉你,如果使用得当,它们是多么强大和可怕!
问题:在多线程环境中,Singleton可能是一个挑战解决方案:使用单线程引导过程来初始化单例的所有依赖项。问题:很难模仿单身汉。解决方案:使用工厂模式进行模拟
您可以将MyModel映射到继承它的TestMyModel类,每当注入MyModel时,您都会得到TestMyModel instread。-问题:单线程可能会导致内存泄漏,因为它们从未处理过。解决方案:好吧,把它们处理掉!在你的应用程序中实现回调以正确处理一个单件,你应该删除所有链接到它们的数据,最后:从工厂中删除它们。
正如我在标题中所说的,singleton不是关于单个实例的。
singleton提高了可读性:您可以查看您的类,看看它注入了什么样的singleton,以确定它的依赖项是什么。singleton改进了维护:一旦你从一个类中删除了一个依赖项,你就删除了一些单例注入,你就不需要去编辑其他类的一个大链接,这些类只是移动了你的依赖项(这是我的臭代码@Jim Burger)Singleton提高了内存和性能:当应用程序中发生了一些事情,并且需要很长的回调链才能传递时,您正在浪费内存和性能,通过使用Singleton,您正在削减中间人,并提高性能和内存使用率(通过避免不必要的局部变量分配)。
因为它们基本上是面向对象的全局变量,所以通常可以用这样的方式设计类,这样就不需要它们了。