Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton class design - null object

Me and a colleague are having a debate:

We have a singleton class that is used at multiple places in our code base.

Originally, the class was designed in such a way that you could get the class object but that object would not be completely initialized.

By this I mean:

mySingleton.getInstance().SomeMethod();

SomeMethod would cause errors because the class was not initialized. For the class to work properly, this would have to happen:

mySingleton.getInstance().initObject();

mySingleton.getInstance().SomeMethod();

Anyways, the debate I have is that the constructor (called with the first get instance) should call initObject so that no errors can be thrown.

What do you think?

My colleague likes it the other way so he knows when the class is getting initialized. (i.e. he calls initObject at 1 specific line of code and hopes that nothing else needs it first).

like image 992
Patrick Lewis Avatar asked Nov 05 '10 21:11

Patrick Lewis


People also ask

Can a singleton be null?

There is a private field which actually holds the reference to the singleton. NULL is a property which instantiates the singleton if not already instantiated and returns it.

What type of design pattern is a null object?

Null Object is a concrete collaborator class that acts as the collaborator for a client which needs one. The null behavior is not designed to be mixed into an object that needs some do nothing behavior.

What is object class null?

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior.

What is the disadvantage of Singleton design pattern?

Disadvantages of a Singleton PatternUnit testing is more difficult (because it introduces a global state into an application). This pattern reduces the potential for parallelism within a program, because to access the singleton in a multi-threaded system, an object must be serialized (by locking).


1 Answers

You're closer to the usual way that the singleton pattern is implemented in Java than your colleague. Please, take a look at Wikipedia. There you will find the 3 most common Java implementations:

Traditional simple way

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

The "solution of Bill Pugh"

public class Singleton {
    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder { 
        public static final Singleton INSTANCE = new Singleton();
    }

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

Traditional simple way using synchronization

public class Singleton {
    // volatile is needed so that multiple threads can reconcile the instance
    // semantics for volatile changed in Java 5.
    private volatile static Singleton singleton;

    private Singleton() {}

    // synchronized keyword has been removed from here
    public static Singleton getSingleton() {
        // needed because once there is singleton available no need to acquire
        // monitor again & again as it is costly
        if (singleton == null) {
            synchronized (Singleton.class) {
                // this is needed if two threads are waiting at the monitor at the
                // time when singleton was getting instantiated
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

Neither of them make use of a separated initObject() method (initialization is supposed to be inside the private constructor). Also notice that if you have a separated, public initObject() method, you may have multi-threading issues...

BTW, personally I rather use the "Bill Pugh" alternative, but the 3 ways are valid.

Edit After the kind Esko comment, I'm adding the following implementation, which is not available on Wikipedia. I just would like to add that 1) The singleton instance is not lazily created like the 3 options above; 2) Since it is a enum, you cannot extend any class; and 3) It is very, very weird. But it seems to be quite hyped on the Java community, so it is here:

Enum way

public enum Singleton {
    INSTANCE;
    Singleton() {
        /* Your init code goes here */
    }
}
like image 107
rsenna Avatar answered Sep 28 '22 16:09

rsenna