我正在使用依赖注入:我应该将哪些类型绑定为单例?

时间:2010-08-13 20:07:53

标签: dependency-injection singleton

关于单身人士是否“不好”以及使用什么样的模式,有很多问题。它们通常专注于单例设计模式,它涉及从类上的静态方法中检索单例实例。这不是其中一个问题。

自从几个月前我真正“发现”依赖注入以来,我一直在推动它在我们的团队中的应用,随着时间的推移从我们的代码中删除静态和单例模式,并尽可能使用基于构造函数的注入。我们采用了约定,因此我们不必继续向DI模块添加显式绑定。我们甚至使用DI框架来提供记录器实例,这样我们就可以自动告诉每个记录器它没有附加代码。既然我有一个地方可以控制各种类型的绑定方式,那么很容易确定特定类别(实用程序类,存储库等)的生命周期应该是什么。

我最初的想法是,如果我希望它们经常被使用,那么将类绑定为单例可能会有一些优势。它只是意味着new正在进行的事情要少得多,特别是当你正在创建的对象最终有一个很大的依赖树时。几乎所有这些类中的非静态字段都是那些被注入构造函数的值,因此在不使用实例时保持实例的内存开销相对较小。

然后我在www.codingwithoutcomments.com上阅读了“Singleton我爱你,但你让我失望”,这让我想知道我是否有正确的想法。毕竟,Ninject默认编译对象创建函数,因此创建这些对象的其他实例时所涉及的反射开销非常小。因为我们将业务逻辑保留在构造函数之外,所以创建新实例是一个非常轻量级的操作。并且对象没有一堆非静态字段,因此创建新实例也不会产生大量内存开销。

所以在这一点上,我开始认为它可能无论多么重要。还有其他考虑因素我没有考虑过吗?是否有人通过改变某些类型物体的生命周期实际上经历了性能的显着改善?遵循DI模式是唯一真正重要的事情,还是有其他原因使用对象的单个实例本来就“坏”?

4 个答案:

答案 0 :(得分:5)

我正在使用单例实例来缓存昂贵的创建对象(如nhibernate会话工厂)或我希望在整个应用程序中共享的对象。

如果处于不确定状态,我宁愿每次使用时都重新创建对象,并将其标记为单例或“每个线程”/“每个请求”/“每个任何”只有在您确实需要的时候。

在所有地方散布单个部分以潜在地保存一些新功能是过早优化并且可能导致非常讨厌的错误,因为您无法确定该对象是新的还是跨多个对象/实例共享。

即使对象目前没有状态并且似乎保存为共享,有人可以稍后重构并向其添加状态,然后可能无意中在不同对象/实例之间共享。

答案 1 :(得分:1)

除非您创建大量对象,否则我不确定内存管理是否是一个大问题。我发现使用IoC容器中的单例有助于处理缓存等问题,在创建缓存对象和连接缓存服务器的过程中,创建过程非常昂贵,因此我们创建缓存对象并重复使用。

单个实例可能有害但是因为它可以在性能方面造成瓶颈,因为在服务的情况下,您有一个实例服务于多个请求。

答案 2 :(得分:0)

对于内存使用而言应该没有多大关系,但是你会增加模块化,使用模拟对象更容易测试,并且必须写出依赖关系明显的审美丑陋将鼓励程序员使每个类更正交和独立。当你的类调用全局变量时,它更容易掩盖依赖关系,单数据基本上就是这样,并且它可以让你的生活更加艰难。

答案 3 :(得分:0)

Gary's answer所述,DI的重点是可测试性(您可以轻松地模拟对类的所有引用,因为它们都在构造函数中列出),而不是运行时性能。

想要做TDD(试驾开发),对吗?