【问题标题】:Singleton Provider vs Regular Provider单例提供者与常规提供者
【发布时间】:2013-02-06 08:52:39
【问题描述】:

我正在尝试(第一次)使用依赖注入来构建令牌。我有一个菱形层次结构问题,我需要将我的数据的签名哈希添加到实际数据本身。

因此,我发现自己多次在原始数据提供者上调用 get()。这很好,但在图表的下方,存在基于时间的组件,因此后续调用返回的数据不同。

建议使用 Singleton Provider 模型的解决方案。对于此提供程序,对 get() 的后续调用返回相同的对象(引用)。此 Provider 缓存第一次调用 get() 的结果并不断返回该结果。在注入依赖项时,我两次注入此提供程序的同一个实例,结果它两次返回相同的数据。

这让我开始思考,是否有任何情况下您不想使用单例提供程序?如果你期望得到不同的结果,是不是应该每次都创建一个新的 Provider 实例?

public MyUnderscoreStringSingletonProvider implements Provider<String>
{
    private final Provider<String> mySomeOtherStringProvider;
    private String myCachedString;

    public MyUnderscoreStringSingletonProvider( 
        Provider<String> someOtherStringProvider )
    {
        mySomeOtherStringProvider = someOtherStringProvider;
        myCachedString = null;
    }

    @Override
    public String get()
    {
        if( myCachedString == null )
        {
            myCachedString = create();
        }
        return myCachedString;
    }

    private String create()
    {
        return "_" + mySomeOtherStringProvider.get();
    }
}

// ...

public class SomeCoolService
{
    // ...

    public Provider<String> injectStringDoubler()
    {
        final Provider<String> stringProvider = 
            injectUnderScoreStringProvider();
        return new TwoConcatendatedStringsProvider(
            stringProvider,
            stringProvider );
        // This would not work if Singleton Provider was not used.
        // Why should we ever use non-Singleton Providers?
    }

    protected Provider<String> injectUnderScoreStringProvider()
    {
        return new MyUnderscoreStringSingletonProvider(
            injectMyTimebasedStringProvider() // returns different result
                                              // depending
                                              // on time.
            );
    }

    // ...
}

【问题讨论】:

  • 你为什么说你在 Java 中有一个菱形层次结构问题?
  • @SenJacob - 这是依赖注入图中的菱形问题。同一个对象需要使用两次,如果没有 Singleton Provider,每次调用 get() 都会是不同的对象。问题是,你为什么不使用单例?有没有这方面的例子可以提供?
  • 初始化一个对象有两种方法,一种是从头开始创建它。另一种是将现有对象重置为其初始状态。如果创建对象的成本比重置它的成本高得多,那么使用预先创建的实例池是有意义的。
  • @BevynQ - 所以不使用预先创建的实例池的唯一好处是减少了内存占用?
  • @studro - 单例更容易实现,池并非微不足道,我只会在万不得已的情况下实现一个。如果一个池已经存在并且易于管理,那就太好了,否则如果我可以摆脱创建和丢弃对象,那么我会的。

标签: java dependency-injection singleton provider


【解决方案1】:

初始化一个对象有两种方法,一种是从头开始创建它。另一种是将现有对象重置为其初始状态。

最终,与软件开发的许多其他事情一样,它归结为对所涉及成本的估计。

Singleton 易于实施,并且在大多数情况下提供了一种资源高效的解决方案, 但是它们不能在非线程安全的条件下使用。例如SimpleDateFormat 作为单例将提供“随机”错误。

对象池在创建对象的成本比重置对象高得多的情况下很有用,但是它们的实现并非易事,因此如果您没有现成的对象并且没有紧迫的理由实现一个然后遵循正常的对象创建/销毁流程是更好的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-03
    • 2019-12-01
    • 2019-12-02
    • 2019-12-01
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多