Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

@Pattern(name="Singleton", scope=Object, purpose=Creational, participants="Singleton")

Package dk.rode.thesis.singleton

Implementations and examples of the Singleton design pattern [Gamma95, p.127].

See:
          Description

Interface Summary
SingletonRegistry<T> A singleton registry is a container for singleton instances of any type, S, inheriting the common super type, T.
 

Class Summary
LoadableSingletonRegistry<T> A loadable singleton registry is a registry that offers the same functionality as StatefullSingletonRegistry, but also allows loading of the actual singleton classes if not already loaded using the LoadableSingletonRegistry.getInstance(String) method.
Main Singleton tests.
MutatedSimpsonsFamilySequence A mutated Simpsons family sequence is a sequence representing a random mutated sub-set of the primary family members in the one and only The Simpsons family.
NorwegianAlphabetSequence A singleton alphabet sequence for letters in the Norwegian alphabet: a though z as well as , , and , all lower-cased.
SimpsonsAndBouvierFamilySequence A Simpsons and Bouvier family sequence is a singleton sequence representing the primary family members in the The Simpsons and Bouvier families.
SimpsonsAndBouvierFamilySequence.Instance An instance container class that when loaded will create the SimpsonsAndBouvierFamilySequence instance to use and return from the SimpsonsAndBouvierFamilySequence.getFamily() method.
SimpsonsFamilySequence A Simpsons family sequence is a singleton sequence representing the primary family members in the one and only The Simpsons family.
SimpsonsFamilySequence.Instance An instance container class that when loaded will create the SimpsonsFamilySequence instance to use and return from the SimpsonsFamilySequence.getFamily() method.
SmileySequence A smiley sequence is a sequence delivering different smileys, e.g. :), *<;), :(, etc.
StatefullSingletonRegistry<T> A statefull singleton registry stores a reference to each acquired singleton instance using a live daemon thread: as long as the registry is not garbage collected, the singleton instances acquired through it will not be garbage collected either.
StatelessSingletonRegistry<T> A stateless singleton registry is a registry with no internal state that allows any type annotated correctly with the Singleton annotation to be fetched, and possibly created, using the StatelessSingletonRegistry.getInstance(Class) method.
 

Enum Summary
DanishAlphabetSequence A singleton alphabet sequence for letters in the Danish alphabet: a though z as well as , , and , all lower-cased.
 

Exception Summary
SingletonException A singleton exception is thrown in case a given type cannot be determined to be a singleton type when requested from a given registry or in case a singleton instance cannot be acquired from a registry.
 

Error Summary
SingletonError A singleton error is thrown because of illegal access to a singleton constructor.
 

Annotation Types Summary
Singleton A singleton annotation identifies a given type already at compile-time as a singleton by identifying the static method returning an instance of the annotated type.
 

Package dk.rode.thesis.singleton Description

Implementations and examples of the Singleton design pattern [Gamma95, p.127].

Intent:

Here, the Singleton participant is represented by the DanishAlphabetSequence, NorwegianAlphabetSequence, SimpsonsFamilySequence, and SimpsonsAndBouvierFamilySequence classes, all but NorwegianAlphanetSequence performing lazy initialisation when the singleton instance is requested. However, synchronisation is not required in either case because Java's standard static initialisation procedures are exploited. The SmileySequence class, which also represents the Singleton participant, therefore illustrates lazy initialisation using synchronisation (see implementation notes in the class JavaDoc for each singleton type for further information).

Singleton Registry functionality in a manner similar to that described by Gamma et al. [Gamma95, p.130-133] is also included in this package. The SingletonRegistry interface represents such a registry, using class tokens as arguments to identify a given singleton instance in the registry using the SingletonRegistry.getInstance(Class) method. Here, however, registry functionality is independent of inheritance as the registry is completely separated from actual singleton types/instances, and registries have no influence over when and how actual singleton instances are created. Furthermore, by declaring an interface to implement for required registry functionality, as opposed to using static methods directly, we get all the standard benefits of object behaviour and polymorhpism at the cost of having to create (possibly singleton) registries as well. For example, a registry implementation may be synchronised or otherwise proxied or decorated, or used as a private member variable in a factory.

Three SingletonRegistry implementations are supplied, namely StatelessSingletonRegistry, StatefullSingletonRegistry, and LoadableSingletonRegistry. All defers the responsibility of creating the singleton objects elsewhere, either directly to the singleton type or to another registry (for the last two).

The StatelessSingletonRegistry is stateless, and can return singleton types annotated with the Singleton annotation. The annotation identifies the static singleton method used to acquire the singleton instance, e.g. getInstance(), and the actual creation of the singleton instance is thus left up to the actual singleton type. Different means of singleton initialisation can therefore be employed "within" the same registry, for example static or lazy initialisation. Here, an annotation is preferred over an interface, because different singleton objects offer no common functionality except for conceptual behaviour in form of only a single instance available. The singleton method must in any case be static, and interfaces cannot declare static methods. An annotation also allows for different method names for different types, which is exemplified by the NorwegianAlphabetSequence.getInstance() and SimpsonsFamilySequence.getFamily() singleton methods.

The StatefullSingletonRegistry is a singleton registry that defers the actual acquiring of singleton instances to another registry, for example StatelessSingletonRegistry, but keeps a reference to each singleton instance that is reachable from a live daemon thread. Hence, as long as the statefull registry is within scope, all acquired singleton instances will be in scope and never be garbage collected.

The LoadableSingletonRegistry extends StatefullSingletonRegistry to provide even more specialised functionality: singleton classes can be dynamically loaded (if not already) based on their class name using the same class loader. The registry only allows singleton types of the proper generic bounds to loaded as well.

UML Class Diagram:

Implementation notes:
Any singleton instance in Java is only a singleton per class loader if created based on and utilising intrinsic class features.

Java does not support multiple functional inheritance. Inheriting private functionality is not possible. Hence, to allow a singleton type to be sub-classed as discussed by Gamma et al. [Gamma95, p.128,130-132], an access modifier of either public or protected must be used for the class, behaviour, and data to be inherited. Any context can access public elements, while members in the same package or sub-classes can access protected elements. This poses potential problems because if a constructor in a singleton class is not declared private, it may be accessed by a given context. Even worse, using reflection, even private members can be accessed if the security manager allows it. Hence, declaring a constructor private is no guarantee that it cannot be invoked.

To remedy this while still allowing singleton types to be sub-classed, the singleton types declared in this package all use the CallerClass or Caller class to establish who the caller of the constructor is; that is, which class and/or member is invoking the constructor. The classes utilises Java's reflection capabilities. The idea is that if the constructor is the private singleton constructor, only the exact same class is allowed to call it. If a sub-class constructor is called, for example a sub-class copy constructor, the constructor checks to see if the caller is a constructor in a sub-class. If so, the call is allowed, otherwise a SingletonError exception is thrown. As an example, the SimpsonsFamilySequence is a singleton type that is allowed to be sub-classed. The SimpsonsAndBouvierFamilySequence class inherits it and is also a singleton type itself, while the MutatedSimpsonsFamilySequence class also inherits it, but is not a singleton type itself. We call types enforcing such runtime access checks for Guarded Types.

However, it would in fact be possible to create a super-singleton instance from a sub-class constructor! A Caller cannot determine how the super-class constructor is invoked from a sub-class, only from where. In the sub-class constructor, the super-constructor could be invoked as super(..) as would be expected, but also by explicitly creating a new instance using new. It does not help to declare the super-singleton type as abstract. Hence, any singleton type that allows sub-classing has to trust the sub-classes to some extent, but must common misuse can be caught with the CallerClass and Caller classes.

An alternative is to use enumerations with a single constant to represent a singleton type. This is illustrated with the DanishAlphabetSequence implementation. We call this the Singleton-as-Single-Constant idiom.

No synchronisation is used in singleton types or in registries!

Author:
Gunni Rode / rode.dk

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.