Friday, November 13, 2015

Design Patterns: Singleton

The word 'singleton' is used to describe a design pattern for objects where only one instance of the object is allowed to exist.

It would technically be possible for you to use nearly any Java class as a singleton by being very, very careful to only create one instance and use it throughout your application.  But why do you want to work that hard?  It's pretty easy to force a class to act as a singleton with a few lines of code.

First of all, we make sure that there is no constructor available to the public.  This means we must create at least one constructor and mark it with the keyword private.  This will keep random objects from just creating their own instances of the class you wish to protect.

    public class MySingletonClass {
        private MySingletonClass() {}
    }

Of course, that means you can't create your single object either!  Never fear, we can get around that.  After all, the singleton class itself can still invoke the constructor.  Since we can't make an instance, though, it will have to be a static method.  I prefer to call it 'getInstance' because that's a good description of what it does.

Of course, it's not safe or desirable to have getInstance just create a new object each time it's called.  So instead we'll store an object reference of the classes' own type inside it and use that:

    public class MySingletonClass {
        private MySingletonClass() {}
        private static MySingletonClass singleton = null;
        ....
        public static MySingletonClass getInstance() {
            ....
            return singleton;
        }
    }

And the rest is just the work that needs to be done to make this function reliably:

     public class MySingletonClass {
        private MySingletonClass() {}
        private static MySingletonClass singleton = null;
        ....
        public static MySingletonClass getInstance() {
            if (null == singleton) {
                singleton = new MySingletonClass();
            }
            return singleton;    
        }
    }

So what have we done here?  We've created a class that can't just be instantiated by anyone.  Instead, we've enforced a contract on client classes, one that states they can only create one copy of this object.  Whichever object attempts to obtain the singleton first will (unknowingly) be responsible for creating it as well in a case of lazy initialization.  The getInstance method is our gatekeeper for this, handing out the same object reference whenever asked:

    MySingletonClass aSingleton = MySingletonClass.getInstance();

As you can see, using it is pretty easy.  You could of course provide parameters to this method and pass them on to the constructor if needed.

No comments:

Post a Comment