GofPatterns Gofpatterns  

Design Patterns  «Prev  Next»
Lesson 1

Introduction to the Singleton Design Pattern

The first design pattern examined in this course is the Singleton Design Pattern The Singleton Design Pattern is used when there should only be one instance of a given class. It uses static, class methods and private constructors to strictly control creation of new instances of the class.
In this module, you will learn:
  1. The ten elements that distinguish a pattern
  2. The intent of the Singleton pattern
  3. When to use the Singleton pattern
  4. The structure of the Singleton pattern
  5. How the Singleton pattern is used in the real world
constructor: A pseudo-method that creates an object.
A singleton class is a class that has a single object and that unique object constitutes a global facility for all clients. For example, consider a program with various classes that need to generate random numbers. It is not a good idea to construct many independent random number generators. The sequence of numbers that a random number generator creates are not truly random but the result of a deterministic calculation.
For that reason, computer-generated random numbers should really be called pseudo-random numbers. In most algorithms for generating a sequence of pseudo-random numbers, you start with a seed value and transform it to obtain the first value of the sequence. Then you apply the transformation again for the next value, and so on.
The Java library uses a linear congruential generator and the seed is transformed according to the equation
seed = (seed * 25214903917 + 11) % 248

Typically, the seed of a random number generator is set to the time at its construction, to some value obtained by measuring the time between user keystrokes, or even to the input from a hardware device that generates random noise. However, for debugging purposes, it is often helpful to set the seed to a known quantity. Then the same program can be run multiple times with the same seed and thus with the same sequence of pseudo-random numbers. For this debugging strategy to be effective, it is important that there is one global random number generator. Let us design a class SingleRandom that provides a single random number generator. The key to ensuring that the class has a single instance is to make the constructor private. The class constructs the instance and returns it in the static getInstance method.
public class SingleRandom{
 private SingleRandom() { generator = new Random(); }
 public void setSeed(int seed) { generator.setSeed(seed); }
 public int nextInt() { return generator.nextInt(); }
 public static SingleRandom getInstance() { return instance; }
 private Random generator;
 private static SingleRandom instance = new SingleRandom();
Note that the static field instance stores a reference to the unique SingleRandom object. Recall that a static field is merely a global variable and in Java, every field must be declared in some class. We find it convenient to place the instance field inside the SingleRandom class itself.
The global variable is one of the old programming practices that creates side effects for the object-oriented programmer.
Global variables tie classes into their context, undermining encapsulation. A class that relies on global variables becomes impossible to pull out of one application and use in another, without first ensuring that the new application itself defines the same global variables. Although this is undesirable, the unprotected nature of global variables can be a greater problem. Once you start relying on global variables, it is perhaps just a matter of time before one of your libraries declares a global that clashes with another declared elsewhere.
By using globals, though, you potentially leave your users exposed to new and interesting conflicts when they attempt to deploy your library alongside others. Globals remain a temptation, however. This is because there are times when the inherent negative side effects of using global access seems a price worth paying in order to give all your classes access to an object. Namespaces provide some protection from this. You can at least scope variables to a package, which means that third-party libraries are less likely to clash with your own system. Even so, the risk of collision exists within the namespace itself.