Many of the examples on the internet and popular Java press do a great job of describing why Singletons are useful and how a Singleton might be constructed, but it's not easy to find a fully function example of a Singleton class, with example uses. This short article shows from beginning to end how a Singleton pattern might work, with references made to problem which shows a Singleton in full swing being used to control a non-modal dialog in a Swing application.
Firstly, in brief, it's worth mentioning what design patterns are all about - The aim of design patterns is to create reusable chunks of code which address a particular programmatic problem and can be transferred between projects and programmers. Well that doesn't sound too ground breaking - afterall, we have all been using class libraries and APIs for years , so what's new? Well the design pattern is really just a description - Rather than being a functional piece of code which you will import for some particular functionality (eg a java package, a CPAN module, or something from PEAR), the design pattern is a pure and abstract description of how a very specific property or behavior can be enforced within a class or a set of classes.
Okay, let's actually take a look at an example. Remember that the Singleton aims to allow just a single instance of a class to exist at any one time. This might be useful for a socket connection to a remote service, or for database connection pooling. In this case I use the example of a dialog box. The situation is that a non-modal dialog box in an applet appears as a separate window which can get lost behind other windows when a confused user uses alt+tab. Re-requesting the dialoge just opens a new one and before too long you have dozens of dialogs kicking around on the user's machine. If instead you use a modal dialog, it would then have the effect of locking out the entire applet when the dialog is alt+tab'ed away from focus, until such a time as it is re-focused and closed.
The solution here is to make the dialog non-modal, so that the applet is still usable, but if the user re-requests that dialog, we want the system to know that one already exists and to return that same instance rather than create a new one.
public class DirectoryBuilder extends JDialog implements ActionListener,KeyListener{
private static DirectoryBuilder DirectoryBuilderInstance = null;
The opening line of the class definition looks normal. In this case I am extending the JDialog class, creating a new class called DirectoryBuilder. This class implements the ActionListener and KeyListener interfaces.
Note that the next line initilalises a DirectoryBuilder object, but sets its value to null. The object isn't instantiated at this stage, but I alreay have an indication that it hasn't been created - just because of its null value. Note that this is the Singleton instance which is at the heart of this designi pattern. This is the instance of the DirectoryBuilder class which will be returned by a getInstance() method which I will show later on.
private DirectoryBuilder(){
setTitle("Singleton dialog");
/* create all the component objects */
name = new JTextField();
number = new JTextField();
.....etc
}
This next snippet of code illustrates another important aspect of the singleton design pattern. This is the constructor method for the class, but note that it is declared private. A private method cannot be called by methods other than those in the same class, so this means that our constructor can't be called from outside the DirectoryBuilder class. This is very different to the usual use of a constructor, which normally returns an object.
public static DirectoryBuilder getInstance() {
if(DirectoryBuilderInstance == null){
DirectoryBuilderInstance = new DirectoryBuilder();
}
return DirectoryBuilderInstance;
}
In this case however, we provide an alternative public interface to the class which enables the constructor to be called internally and the new DirectoryBuilder object to be returned. This getInstance() method tests to see if the instance of DirectoryBuilder is still null. If it is, then we instantiate a new one by calling the constructor in the usual way. If the DirectoryBuilder instance is not null, then all we have to do is return a reference to the existing object. The key here is that a new object isn't instantiated, because the constructor isn't called. All we do essentially is return a pointer to the existing singleton object.
To see how this class might be used, take a look below at the actionPerformed method which might reside in some GUI framework. The event triggers the dialog's getInstance() method,
public void actionPerformed(ActionEvent e) {
DirectoryBuilder dbuild = DirectoryBuilder.getInstance();
DirectoryBuilder.getInstance().setVisible(false);
DirectoryBuilder.getInstance().setVisible(true);
}
So this final snippet of code shows how the instance of our singleton class is retrieved from it's getInstance() interface. The extra two lines with calls to setVisible are a sneaky hack which I use to get focus on the newly created (or re-retrieved) dialog object. The toFront() and requestFocus() methods aren't always reliable on some JVM's, but toggling visibility is a sure fire way of forcibly getting focus on a component.
That small diversion concludes this article on Singleton design patterns. Please feel free to hit the reply button and leave your comments below, or subscribe to this channel to receive a notice when a new article/tutorial is posted here under the Java section.
Signing out,
christo