我目前正在通过阅读 books 来“更新”我的开发知识,尤其是 TDD 原则方面的知识。 ,网络上的文章和观看videos 。到处都会弹出警告,不要使用全局状态变量,因为它们会使系统脆弱且不易测试,并且由于单例并没有更好或相同,所以也不要使用它们。
现在我想知道:我真的可以在这一点上保持一致吗?
- 应用程序使用缓存怎么样,这样它就不必一次又一次查找常用的数据库对象?我需要传递该缓存的单个实例,否则还有什么意义?
- 另一个例子是 DAO,或者我们称之为提供商。它们除了为我们提供 JPA 数据库访问之外什么也不做,但除此之外没有任何状态。那么为什么不让它们成为单例呢?
- 网络前端的 Controller 呢?他们所做的只是对请求使用react——同样没有内部状态。
一次又一次实例化后两者岂不是会浪费大量性能吗?我确信还有更多适用于此的示例。
也许使用单例就可以了,只要它们除了final之外没有任何成员变量?
即使它们有成员变量,但所有的成员变量都被注入(inject)到它们中,也应该保存使用它们,因为任何对象,无论是否是单例,都可以修改注入(inject)的对象,所以它实际上没有任何区别。
我对整个“避免单例”业务有点困惑,我什至不确定我是否完全理解所涉及的风险。但最重要的是,我想听听对上述示例的想法,因为这些是我们应用程序中最常见使用单例的地方。
谢谢!
顺便说一句:我们正在使用 springs 依赖注入(inject),所以如何去做不是我的问题,而是为什么要避免它以及哪里可以。
最佳答案
单例的问题不在于单例设计模式本身,而在于它们作为有状态的全局上帝对象在应用程序中被过度使用。
这种使用方式有两个主要缺点:
对单例的依赖是隐藏的依赖,对象与它们紧密耦合,这阻碍了代码的可发现性、可维护性和可测试性。
对象依赖于单例,它们不知道它们处于哪种状态。这里和那里使用单例行为的顺序开始变得重要,并且您开始看到“MySingleton.Initialize( )"到处都是,这是危险的,并且违背了拥有单个实例的全部目的。
在我看来,只有克服这些陷阱的单例才值得考虑——这意味着无状态、不可变的对象以某种方式注入(inject)到它们的消费者中,并且可以被具有相同合约的其他实例替换。
除此之外,单例化通常是对错误对象应用的过早优化。
这篇博文几乎总结了这一点:http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
关于caching - 避免单例和全局变量——但是缓存、提供者、 Controller ……呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9308034/