使用依赖注入作为单例的替代方案

Posted

技术标签:

【中文标题】使用依赖注入作为单例的替代方案【英文标题】:Using Dependency Injection as an alternative to Singletons 【发布时间】:2011-08-22 08:58:42 【问题描述】:

我一直都知道单例是“坏的”,但直到我从 C++ 迁移到 Java 之后,我才决定找到解决它们的方法。通过阅读,我发现工厂或依赖注入都可以完成这项工作,但我想对此进行一些确认。

举个例子,我准备写一个 AnimationCache 单例来存储Map<String, Animation>。不同的类应该能够(基本上)在任何地方访问这个类,以便它们可以轻松有效地加载动画。一个非常简短的例子来说明使用 DI 的等效代码会是什么样子。

另外,Guice 是一个用于非 Web 应用程序的 DI 的好框架吗?我使用 Spring 进行 Web 开发,但我不太确定它是否适用于游戏。

【问题讨论】:

Spring DI 不仅适用于 Web 应用程序。 更新:您可能还想考虑CDI 2.0 – Contexts & Dependency Injection for Java。截至 2017 年 4 月,在 JSR 365 中标准化。专为 Java SE 和 Java EE 设计。 这个问题及其答案可能与未来的读者有关:***.com/questions/130794/… 【参考方案1】:

Spring 和 Guice 都可以。我个人更喜欢 Guice 用于纯依赖注入,但 Spring 提供的更多。

代码看起来像这样:

public class AnimationCacheClient 

    private AnimationCache cache;

    @Autowired // for Spring, or
    @Inject // for Guice (but I think Spring also supports it now)
    public AnimationCacheClient(AnimationCache cache) 
        this.cache = cache;
    

    // ...

我个人更喜欢构造函数注入,但您也可以使用 setter 注入或字段注入。

但请注意,DI 的目的不是“简单的单例”。它的主要目的是通过注入模拟依赖项(这里是模拟AnimationCache 实例),使代码(这里是AnimationCacheClient)易于单元稳定。

【讨论】:

感谢代码示例。这看起来很简单。所以我假设依赖注入可以代替单例是错误的?我真的在寻找一种更好的方法来让代码访问一个应该只有一个的类。 不,你没有错。默认情况下,Spring bean 是单例的。 Guice bean 默认是原型,但可以配置为单例。我只是想指出,DI 的主要目标不是让单例变得容易。它的主要目标是简化测试。【参考方案2】:

使用 Spring,DI 非常简单。使用 @Autowired 注释,您甚至不需要额外的 xml 来连接东西或设置方法。班级中需要访问以前单身人士的成员即可。

这是一个很好的例子:http://www.developer.com/java/other/article.php/3756831/Java-Tip-Simplify-Spring-Apps-with-Autowired.htm

【讨论】:

【参考方案3】:

我最近在 Singleton 上 'withnessed' 这个thread 以及它可能有多糟糕(或没有)以及你可以做些什么来绕过它。值得一读。

【讨论】:

以上是关于使用依赖注入作为单例的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

注入服务的构造函数何时运行?

为什么喜欢模板方法而非依赖注入?

Net Core依赖注入

Spring中AOP主要用来做什么。Spring注入bean的方式。什么是IOC,什么是依赖注入

NSManagedObjectContext 的单例?死板的?依赖注入?

Spring Bean注入/单例理解/循环依赖