What's Alternative to Singleton

JavaDesign PatternsSingleton

Java Problem Overview


We have a class that holds configuration information for the application. It used to be a singleton. After some architectural review, we were told to remove the singleton. We did see some benefits of not using singleton in the unit testing because we can test different configurations all at once.

Without singleton, we have to pass the instance around everywhere in our code. It's getting so messy so we wrote a singleton wrapper. Now we are porting the same code to PHP and .NET, I am wondering if there is a better pattern we can use for the configuration object.

Java Solutions


Solution 1 - Java

The Google Testing blog has a series of entries about avoiding Singleton (in order to create testable code). Maybe this can help you:

The last article explains in detail how to move the creation of new objects into a factory, so you can avoid using singletons. Worth reading for sure.

> In short we move all of the new operators to a factory. > We group all of the objects of similar lifetime into a single factory.

Solution 2 - Java

The best way is to use a Factory pattern instead. When you construct a new instance of your class (in the factory) you can insert the 'global' data into the newly constructed object, either as a reference to a single instance (which you store in the factory class) or by copying the relevant data into the new object.

All your objects will then contain the data that used to live in the singleton. I don't think there's much of a difference overall, but it can make your code easier to read.

Solution 3 - Java

I might be stating the obvious here, but is there a reason why you can't use a dependency-injection framework such as Spring or Guice? (I believe Spring also is available for .NET as well now).

That way, the framework can hold a single copy of the configuration objects, and your beans (services, DAOs, whatever) don't have to worry about looking it up.

This is the approach I usually take!

Solution 4 - Java

If you use Spring Framework, you can just create a regular bean. By default (or if you explicitly set scope="singleton") only one instance of the bean is created and that instance is returned every time the bean is used in a dependency or retrieved via getBean().

You get the advantage of the single instance, without the coupling of the Singleton pattern.

Solution 5 - Java

The alternative is passing in what you need instead of asking an object for things.

Solution 6 - Java

don't accumulate responsibilites to a single configuration object since it will ends in a very big object that is both difficult to understand and fragile.

For example if you need another parameter to a particular class you change the Configuration object, then recompile all the classes that uses it. This is somewhat problematic.

Try refactoring your code to avoid a common, global and big Configuration object. Pass only required parameters to client classes:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

should be refactored to:

 class Server {
   
    public Server(int port) {
       this.port = port;
    }
 }

a dependency injection framework will help a lot here, but it isn't stricly required.

Solution 7 - Java

You can accomplish the same behavior of singleton by using static methods. Steve yegge explains it very well in this post.

Solution 8 - Java

Is a class that contains only static methods and fields possible? I'm not sure of exactly what your situation is, but it might be worth looking into.

Solution 9 - Java

Maybe not very clean either, but you could maybe pass the information bits you want to have changed to the method that creates the singleton -- instead of using

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

you could call createSingleton(Information info) directly on application startup (and in the setUp-Methods of the unit tests).

Solution 10 - Java

Depends on what tooling/frameworks etc.. are being used. With dependency injection/ioc tools one can often still get singleton performance/optimizations by having the di/ioc container use singleton behaviour for the class required - (such as a IConfigSettings interface) by only ever creating one instance of the class. This could be still substituted out for testing

Alternately one could use a factory to create the class and return the same instance each time you request it - but for testing it could return a stubbed/mocked version

Solution 11 - Java

Review possibility to make configuration as callback interface. So your configuration sensitive code will look:

MyReuseCode.Configure(IConfiguration)

System-init code will look:

Library.init(MyIConfigurationImpl)

Solution 12 - Java

You could use a dependency injection framework to ease the pain of passing in the configuration object. A decent one is ninject which has the advantage of using code rather than xml.

Solution 13 - Java

Singletons are not evil but the design pattern is flawed. I have a class that I only want to create a single instance of it during runtime but want to create multiple isolated instances during unit testing to ensure deterministic results.

DI using Spring, etc, is a very good option but not the only option.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn MillView Question on Stackoverflow
Solution 1 - JavaFrankSView Answer on Stackoverflow
Solution 2 - JavagbjbaanbView Answer on Stackoverflow
Solution 3 - Javauser7094View Answer on Stackoverflow
Solution 4 - JavaGene GotimerView Answer on Stackoverflow
Solution 5 - JavakoenView Answer on Stackoverflow
Solution 6 - JavadfaView Answer on Stackoverflow
Solution 7 - JavaYoussefView Answer on Stackoverflow
Solution 8 - JavaThomas OwensView Answer on Stackoverflow
Solution 9 - JavaRoland EwaldView Answer on Stackoverflow
Solution 10 - JavasaretView Answer on Stackoverflow
Solution 11 - JavaDewfyView Answer on Stackoverflow
Solution 12 - JavaColin GravillView Answer on Stackoverflow
Solution 13 - JavacodematrixView Answer on Stackoverflow