2

我最近受到了我的观点的挑战,即单例只适用于日志记录和配置。有了依赖注入,我现在看不到你不能将服务或存储库用作单例的原因。

没有耦合,因为 DI 通过接口注入单例实例。唯一合理的论点是您的服务可能具有共享状态,但如果您考虑一下,服务应该是没有任何共享状态的独立单元。是的,它们确实被注入了存储库,但是您只有一种方法可以创建存储库实例并将其传递给服务。由于存储库永远不应该具有共享状态,因此我看不出它也不能是单例的任何原因。

例如,一个简单的服务类如下所示:

public class GraphicService : IGraphicService
{
    private IGraphicRepository _rep;
    public GraphicService(IGraphicRepository rep)
    {
       _rep = rep;
    }

    public void CreateGraphic() 
    {
      ...
      _rep.SaveGraphic(graphic):
    }
}

服务中不共享任何状态,除了存储库,它也不会更改或拥有自己的状态。

所以问题是,如果您的服务和存储库没有任何状态并且仅通过接口、配置或其他任何以与它们相同的方式实例化的方式传入,那么您为什么不将它们作为单例呢?

4

2 回答 2

3

如果您使用的是单例模式,即类的静态属性,那么您就会遇到紧耦合问题。

如果您只需要一个类的单个实例,并且使用 DI 容器来控制其生命周期,那么这不是问题,因为没有任何缺点。该应用程序不知道有一个单例,只有 DI 容器知道它。

归根结底,一个类的单个实例是一个有效的编码要求,唯一的问题是你如何实现它。Di Container 是最好的方法。Singleton 模式适用于对可维护性和测试不够关心的快速脏应用程序。

于 2013-10-13T14:18:20.140 回答
0

一些项目在依赖注入被填充之前使用单例进行依赖查找。例如 iBATIS jpetstore 如果我没记错的话。你可以很方便地访问你的依赖,就像

public class GraphicService : IGraphicService
{
    private IGraphicRepository _rep = GraphicRepository.getInstance(); 


    public void CreateGraphic() 
    {
        ...
        _rep.SaveGraphic(graphic):
    }
}

但这会损害可测试性(因为不容易用测试替身替换依赖)并引入隐式强依赖(IGraphicService 依赖于抽象和实现)。

依赖注入解决了这些问题。我不明白为什么不能在您的情况下使用单例,但是在使用 DI 时它并没有增加太多价值。

于 2013-10-12T01:09:16.740 回答