I'm attempting (for the first time) to build up a token using dependency injection. I have a diamond hierarchy problem, where I need to prepend a signed hash of my data to the actual data itself.

As a result, I find myself calling get() on the original data provider multiple times. This would be fine, but further down the graph, there are time-based components and as a result, the data returned on subsequent calls is different.

A solution was suggested to use the Singleton Provider model. For this Provider, subsequent calls to get() return the same object (reference). This Provider caches the result of the first call to get() and continually returns that. When injecting dependencies, I inject the same instance of this provider twice, and as a result it returns the same data twice.

This got me thinking, is there any situation where you wouldn't want to use a Singleton Provider? If you expect a different result, shouldn't a new Provider instance be created every time?

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.
            );
    }

    // ...
}
有帮助吗?

解决方案

There are two ways on initializing an object one it to create it from scratch. The other is to reset an existing object to it's initial state.

Ultimately like a lot of other things with software development it comes down to an estimate of costs involved.

Singletons are easy to implement and in most cases provide a resource efficient solution, however they cannot be used in non thread safe conditions. e.g. SimpleDateFormat as a singleton will provide "random" errors.

Object-Pools are useful in these situations where the cost of creating the object is significantly more expensive than resetting it, however they are not trivial to implement so if you do not have a ready made one and there is no pressing reason to implement one then following normal Object Create/Destroy flow is the better approach.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top