为什么我不应该将我的服务做成单例(IOC)?

8
重要提示:请注意,我不是指具有私有构造函数和静态实例变量(或者如某些人建议的静态类)的单例模式,而是单例模式在应用程序生命周期内从反转控制容器返回相同实例。
许多容器默认使用短生命周期。无论是每个依赖项(或每个请求)一个新实例,还是每个作用域(例如HTTP请求)一个实例。
我想知道为什么容器推广短寿命对象而不是长寿命对象?
请注意,我通常只在容器中注册我的服务。如果需要创建领域模型等,则在容器中注册工厂。

2
我认为你是指Singleton模式中的单例,而不是静态类中的Singleton。 - johnny g
2
在应用程序生命周期中从我的控制反转容器返回相同的实例,这在功能上与单例模式是相同的,只是没有在类级别上实现。无论哪种方式,它都是一个单例。 - Igby Largeman
单例模式并不是静态类,至少不符合GOF的定义。我在问题中加入了这段文字,以防止有关单例模式定义的评论,使得更多人关注实际问题。不过我可能两方面都失败了... 重要的是你明白我的意思。请自由回答问题吧。 - jgauffin
在编程中,IMO服务通常应该是长期存在的。如果你需要在整个会话期间使用它,为什么要一遍又一遍地拆除和重建它呢?也许只有当它占用大量内存且你想保持最小内存占用时才会这样做?或类似情况。但这只是规则的例外,所以我赞同你的观点。(我所使用的唯一一个IOC容器是我自己编写的,它默认使用长期存在的对象。) - Igby Largeman
2个回答

2

进行了更多的研究。

因为使用较短的生命周期可以更容易地处理会话特定信息。混合使用不同的生命周期可能会使事情变得复杂。

每次在单个实例服务中使用作用域依赖项时,它将在开始时正常工作。但是,作用域服务通常不设计为长期存在。如果它们使用外部资源,如套接字连接或数据库连接,则可能会在某一点上丢失。

由于作用域服务并非设计为此,因此它可能会开始失败,从而导致单个实例服务也开始失败,并继续这样做,直到应用程序重新启动。


有人黑了我的WordPress网站。 :( 已删除该链接。 - jgauffin

0

很大程度上取决于您的服务正在做什么。如果存在一些共享状态,通常会选择单例模式,因此围绕该状态的同步可能会导致瓶颈,从而影响可扩展性。如果没有共享状态,则仍然可以选择单例模式,但必须小心,不要在将来某个时刻引入任何共享状态(或者如果您这样做,那么您需要有效地锁定它)。

如果每次返回服务的新实例,则无需担心,这可能会导致更好的可扩展性/灵活性,尽管返回新实例也可能会影响可扩展性,如果该实例持有稀缺资源(例如db连接)。

因此,我认为真正的答案是“取决于情况”。如果您查看框架如何处理此问题,通常是一些中间解决方案,例如维护服务池(例如db连接池)或Wcf的“每个会话”模型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接