简体   繁体   English

SIngleton对象初始化和依赖注入

[英]SIngleton object initialization and dependency injection

I usually create singleton classes using singleton holder pattern like this: 我通常使用单例持有人模式创建单例类,如下所示:

public class Foo {

    private static final class SingletonHolder {
        private static final Foo INSTANCE = new Foo();
    }  

    private Foo(){}

    public static final Foo getInstance(){
        return SingletonHolder.INSTANCE;
    }

}

Everything ok. 一切还好。 But, what about if I need inject one dependency to initialize the singleton object? 但是,如果我需要注入一个依赖项来初始化单例对象该怎么办?

In that case, I add one method initialize that receives the dependency and must be called just one time: 在这种情况下,我添加了一个方法initialize来接收依赖项,并且必须仅调用一次:

public class Foo {

    private static final class SingletonHolder {
        private static final Foo INSTANCE = new Foo();
    }  

    private Foo(){}

    public static final void initialize(Dependency d) {
        SingletonHolder.INSTANCE.setDependency(d);
    }

    public static final Foo getInstance(){
        return SingletonHolder.INSTANCE;
    }

}

Am I in the right way? 我做对了吗? Is there another solution? 还有其他解决方案吗? I know that it depends on the program, my logic and so on... but how generally should be solved this problem? 我知道这取决于程序,我的逻辑等等……但是应该如何普遍解决这个问题呢?

The problem with this approach is that the initialize method can be invoked more than once, and there is no indication in your code that setting the dependency is being handled with thread safety. 这种方法的问题在于, initialize方法可以被多次调用,并且在您的代码中没有迹象表明设置依赖项是通过线程安全来处理的。

If you're fine with that, then your lazy initialization idiom is fine. 如果您对此表示满意,那么您的惰性初始化习惯就可以了。

Otherwise, you could throw an IllegalStateException or otherwise silently do nothing when the dependency is being set more than once within your singleton instance. 否则,当在您的单例实例中多次设置依赖项时,您可能会抛出IllegalStateException或以其他方式静默地不执行任何操作。

Edit 编辑

As Andy Thomas says, you also aren't checking whether the dependency is set before getInstance is invoked, or at least your code doesn't display it. 正如安迪·托马斯Andy Thomas)所说,您也不会检查是否在调用getInstance之前设置了依赖项,或者至少您的代码没有显示它。

I think you are overcomplicating it. 我认为您太复杂了。 In a few places I worked (including my current one) we don't try to enforce singletons. 在我工作过的几个地方(包括当前的地方),我们不尝试强制执行单例。 All the wiring for the actual application is done in one place, so if you searched for usages of constructor you should find one in src and probably multiple in test . 实际应用程序的所有连接都在一个地方完成,因此,如果您搜索构造函数的用法,则应在src找到一个,在test可能找到多个。 See the code below. 请参见下面的代码。

A few disadvantages of your approach: 您的方法的一些缺点:

  • you lose immutability, Foo 's dependency can change 如果失去不变性, Foo的依赖关系就会改变
  • both setDependency and initialize methods are test code in production setDependencyinitialize方法都是生产中的测试代码
  • your constructor doesn't create a valid object, a second half of constructor is in initialize method which you have to remember to call after calling constructor 您的构造函数未创建有效的对象,构造函数的后半部分位于initialize方法中,您必须记住在调用构造函数后调用
  • SingletonHolder is a boiler plate code, I am not sure why don't you just declare public static final Foo instance field instead? SingletonHolder是样板代码,我不确定为什么不只声明public static final Foo instance字段?
  • it is still possible to create multiple instances of Foo using reflection API and object serialisation mechanisms 仍然可以使用反射API和对象序列化机制创建Foo多个实例
public class Foo {

    private final Dependency dependency;

    public Foo(Dependency dependency) {
        this.dependency = dependency;
    }

    // ...
}

public class Dependency {
    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM