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

6
我一直知道单例模式是“不好”的,但只有现在我从C++转到Java才决定找到解决方法。通过一些阅读,我发现工厂模式或依赖注入可能能胜任此工作,但我想得到确认。
例如,我打算编写一个AnimationCache单例,该单例将存储一个Map<String,Animation>。不同的类应该能够在任何地方轻松高效地访问此类,以便它们可以轻松有效地加载Animations。使用DI等效代码的非常简要的示例将是很棒的。
另外,Guice是用于非Web应用程序的DI的好框架吗?我已经在Web开发中使用了Spring,但我不确定它是否适用于游戏。

Spring DI 不仅适用于 Web 应用程序。 - gtiwari333
更新:您可能还想考虑使用CDI 2.0 - Java上下文和依赖注入。自2017年4月起,已在JSR 365中标准化。旨在为Java SE和Java EE提供支持。 - Basil Bourque
这个问题及其答案可能与未来的读者相关:https://dev59.com/Y3VC5IYBdhLWcg3w-WSs?rq=1 - Cypher
3个回答

5

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的目的不是为了拥有“简单的单例”。它的主要目的是使代码(这里是AnimationCacheClient)易于进行单元测试,通过能够注入模拟依赖项(这里是模拟的AnimationCache实例)。

感谢提供代码示例。看起来很简单。那么我之前认为依赖注入可以取代单例模式是错的吗?我真的正在寻找一种更好的方式,让代码可以访问只应该存在一个实例的类。 - Mitch
不,你没有错。默认情况下,Spring的bean是单例的。Guice的bean默认是原型的,但可以配置为单例。我只是想指出依赖注入的主要目标不是为了让单例变得容易。它的主要目标是使测试变得容易。 - JB Nizet

1

最近我看到了这个线程,讨论了Singleton模式的优缺点以及如何绕过它。非常值得一读。


1

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