避免单例和全局变量 - 但缓存,提供程序,控制器......等等?

时间:2012-02-16 08:46:35

标签: caching controller tdd singleton global-variables

我正在通过阅读books,网上文章和观看videos来“更新”我的开发知识,尤其是TDD原则。在任何地方出现的东西都是警告,不要使用全局状态变量,因为它们会使系统变得脆弱而不易测试,因为单身人士不是更好或者更相同,也不会使用它们。

现在我想知道:我能真正对此保持一致吗?

  • 应用程序使用的缓存怎么样,所以它不必一次又一次地查找常用的数据库对象?我需要传递一个缓存的单个实例,否则会有什么意义呢?
  • 另一个例子是DAO或我们称之为提供者。他们什么也不做,只为我们提供JPA数据库访问,但没有状态。那么为什么不让他们单身呢?
  • 网络前端的控制器?他们所做的就是对请求做出反应 - 再次没有内部状态。

难道不会浪费很多性能一次又一次地实例化后两者吗?我确信还有一些例子适用。

也许可以使用单身,只要他们除了决赛之外没有任何成员变量?

即使他们有成员变量但是所有成员都被注入其中,它应该保存以使用它们,因为任何对象,单独或不单独,都可以修改注入的对象,因此它确实没有任何区别。 / p>

我对整个“避免单身”业务感到有点困惑,我甚至不确定我是否完全了解所涉及的风险。但最重要的是我想听听上面这些例子的想法,因为这些是我们使用单例的应用程序中最常见的地方。

谢谢!

顺便说一句:我们正在使用弹簧依赖注入,所以如何做到这不是我的问题,而是为什么要避免它以及哪里可以。

3 个答案:

答案 0 :(得分:1)

您绝对正确 - 有些情况需要单个实例。然而,“避免单身”业务并不能说明他们不需要。根据我的理解,它指出单例行为应该由Dependency Container添加,而不是由静态实例添加。

这将允许您在单元测试中模拟它,同时只有一个实例在生产中。您可能会发现此链接很有用:Object Scopes in Ninject

答案 1 :(得分:1)

单身人士的问题不在于单身人士的设计模式本身,因为他们被覆盖在幕后,因为有状态的全球上帝反对所有应用程序。

使用它们的方式有两个主要缺点:

  • 对单例的依赖是隐藏的依赖关系,对象与它们紧密耦合,这妨碍了代码的可发现性,可维护性和可测试性。

  • 对象依赖于单身人士,他们不知道他们所处的状态。单身人士的行为在这里使用的顺序开始变得重要,你开始看到“MySingleton.Initialize”( )“遍布整个地方,这是危险的,并且打破了单一实例的全部目的。

只有胜过这些陷阱的单身人士才值得考虑 - 这意味着无状态,不可变的对象以某种方式被注入他们的消费者,并且可以被其他具有相同合同的实例所取代。

除此之外,Singleton -ification通常是对错误对象应用的过早优化。

这篇博文非常总结:http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx

答案 2 :(得分:0)

单例和全局变量的问题在于我们需要它们,但大多数编程语言只提供一个"全局"上下文。

想象一下,你可以这样做:

 Global g1 = new Global();
 g1.run( ... some code ... );

 Global g2 = new Global();
 g2.run( ... some code ... );

当代码由g2运行时,g1运行中的单例和全局变量都不可见。这实际上就是我们想要的:高效的方式说"好吧,我完成了全局和东西,摆脱它们&# 34。

该解决方案是一个工厂,可以为您构建所有单例和全局变量,并将它们放入正确位置的代码中。然后,您可以根据需要在测试中创建此工厂的新实例(以及新的单例和全局)。

这就是"依赖注入"就是这样。这是short introduction