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

dk.rode.thesis.singleton
Class SimpsonsFamilySequence

java.lang.Object
  extended by dk.rode.thesis.meta.model.AbstractSequence<E>
      extended by dk.rode.thesis.meta.model.ArraySequence<String>
          extended by dk.rode.thesis.singleton.SimpsonsFamilySequence
All Implemented Interfaces:
Sequence<String>, Copyable<Sequence<String>>, StrictCopyable<Sequence<String>>, Stringable<Sequence<String>>
Direct Known Subclasses:
MutatedSimpsonsFamilySequence, SimpsonsAndBouvierFamilySequence

@Participant(value="Singleton")
@Singleton(value="getFamily")
public class SimpsonsFamilySequence
extends ArraySequence<String>

A Simpsons family sequence is a singleton sequence representing the primary family members in the one and only The Simpsons family.

Only a single instance of this class is created, on demand only, and is available via the getFamily() method. However, sub-classing is allowed using the supplied sub-class and/or copy constructors. If any other context than a sub-class tries to invoke these constructors, a SingletonError is thrown! Hence, the singleton invariant is still enforced even though sub-classing is allowed, and sub-classes may or may not be singletons.

Implementation notes:
The SimpsonsFamilySequence utilises a static inner class to store the actual singleton instance. Unlike the DanishAlphabetSequence class, the instance is therefore not created at the class loading time, but the first time getFamily() is invoked, i.e. lazily initialised. Therefore, for example, accessing the static field SIZE will not cause the singleton instance to be created. The initialisation utilises standard static initialisation (of the inner class), and the getFamily() method need not be synchronised. This corresponds to the initialise-on-demand holder class idiom [Bloch01, p.194].

The check to see if it is a sub-class that is invoking a sub-class constructor is done using a Caller instance. It utilises Java's reflection capabilities. Acquiring a sub-class instance before the getFamily() method has been invoked will not cause the singleton instance to be created. Sub-class constructors are declared protected, but even if they had been public, the sub-class check would still work. But, by declaring them protected, we only have to worry about objects in the same package illegally invoking the constructors. However, using reflection, even private members can be accessed if the security manager allows it, but the sub-class check will still work if reflection is used. There is furthermore a check in the private constructor that ensures that SimpsonsFamilySequence instances cannot be created using reflection (the same goes for the other singleton types declared in this package!). The SimpsonsFamilySequence class is thus a Guarded Type.

Though not implemented, this class could implement java.io.Serializable. If so, the serialization should override the serialization methods writeReplace() and readResolve(), the latter always returning the singleton instance. It does not implement java.lang.Cloneable, either (to throw an exception), because otherwise sub-classes cannot become cloneable. It is ok for a sub-class to invoke super.clone() because that will correspond to Object.clone(), which will return an instance of the sub-class, not this sequence. This is illustrated in the MutatedSimpsonsFamilySequence sub-class.

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

Though the standard ArraySequence hashCode and equals(Object) works for singleton sub-classes of it, faster versions of the two are implemented here to take advantage of the singleton behaviour.

Author:
Gunni Rode / rode.dk
See Also:
DanishAlphabetSequence, NorwegianAlphabetSequence, SimpsonsAndBouvierFamilySequence, SmileySequence, MutatedSimpsonsFamilySequence

Nested Class Summary
private static class SimpsonsFamilySequence.Instance
          An instance container class that when loaded will create the SimpsonsFamilySequence instance to use and return from the getFamily() method.
 
Nested classes/interfaces inherited from interface dk.rode.thesis.meta.model.Sequence
Sequence.State
 
Field Summary
(package private) static String[] members
          The primary members in The Simpsons family.
static int SIZE
          The number of primary members in The Simpsons family.
 
Fields inherited from class dk.rode.thesis.meta.model.ArraySequence
elements, index
 
Fields inherited from class dk.rode.thesis.meta.model.AbstractSequence
state
 
Constructor Summary
private SimpsonsFamilySequence()
          Private no-arg constructor for singleton creation.
protected SimpsonsFamilySequence(SimpsonsFamilySequence sequence)
          Sub-class copy constructor constructor.
protected SimpsonsFamilySequence(String... members)
          Sub-class constructor.
 
Method Summary
 SimpsonsFamilySequence copy()
          Returns this instance.
 boolean equals(Object object)
          Returns true if object is an array sequence having the same type as this array sequence, using an equivalent array, and is at the same sequence index, false if not.
static SimpsonsFamilySequence getFamily()
          Returns the SimpsonsFamilySequence singleton instance to use.
 int hashCode()
          Returns the hash code of this sequence.
 
Methods inherited from class dk.rode.thesis.meta.model.ArraySequence
bounded, consistent, current, next, reset, size, unique
 
Methods inherited from class dk.rode.thesis.meta.model.AbstractSequence
getStringablePolicy, state, toString, toString
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface dk.rode.thesis.meta.model.Sequence
state
 
Methods inherited from interface dk.rode.thesis.strategy.Stringable
getStringablePolicy, toString
 

Field Detail

members

static final String[] members
The primary members in The Simpsons family.


SIZE

public static final int SIZE
The number of primary members in The Simpsons family.

Implementation notes:
Accessing this static field will before getFamily() will not cause the singleton instance to be created!

See Also:
DanishAlphabetSequence.SIZE, NorwegianAlphabetSequence.SIZE, SimpsonsAndBouvierFamilySequence.SIZE, SmileySequence.SIZE
Constructor Detail

SimpsonsFamilySequence

private SimpsonsFamilySequence()
Private no-arg constructor for singleton creation.

Throws:
SingletonError - If another class tries to invoke this constructor (via reflection).

SimpsonsFamilySequence

protected SimpsonsFamilySequence(SimpsonsFamilySequence sequence)
Sub-class copy constructor constructor.

Only a sub-class of this sequence can invoke this constructor! Any other context invoking it will cause a SingletonError to be thrown.

Parameters:
sequence - The sequence to copy; cannot be null.
Throws:
NullPointerException - If sequence is null.
SingletonError - If a non sub-class context tries to invoke this constructor.

SimpsonsFamilySequence

protected SimpsonsFamilySequence(String... members)
Sub-class constructor.

Only a sub-class of this sequence can invoke this constructor! Any other context invoking it will cause a SingletonError to be thrown.

Parameters:
members - The family members of the family; cannot be null, or empty.
Throws:
NullPointerException - If members is null.
IllegalArgumentException - If members is empty.
SingletonError - If a non sub-class context tries to invoke this constructor.
Method Detail

copy

public SimpsonsFamilySequence copy()
Returns this instance.

Returns:
This instance; never null.

equals

public boolean equals(Object object)
Description copied from class: ArraySequence
Returns true if object is an array sequence having the same type as this array sequence, using an equivalent array, and is at the same sequence index, false if not.

Overrides:
equals in class ArraySequence<String>
Parameters:
object - The object to test; can be null.
Returns:
True if equal, false if not.

getFamily

public static SimpsonsFamilySequence getFamily()
Returns the SimpsonsFamilySequence singleton instance to use.

The singleton instance is not created before the first time this method is invoked!

Implementation notes:
Because this method is static it cannot be overridden. However, it cannot be declared final because we support singleton inheritance: a class does not allow two static methods with the same signature. So, if declared final, sub-classes could not define their own getFamily method to hide this method to return the proper instance.

Returns:
The Simpsons family sequence; never null.
See Also:
Singleton

hashCode

public int hashCode()
Description copied from class: ArraySequence
Returns the hash code of this sequence.

Overrides:
hashCode in class ArraySequence<String>
Returns:
The hash code.

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.