SDSU CS 635: Advanced Object-Oriented Design & Programming
Spring Semester, 1998
Singleton

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Apr-98

Contents of Doc 5, Singleton

...References slide # 1
...Singleton slide # 2
......Intent slide # 2
......Motivation slide # 2
......Applicability slide # 2
......Implementation slide # 5
......Singleton and Inheritance slide # 6
.........C++ Solution 1 slide # 8
.........C++ Solution 2 - Registry slide # 9
.........Java Solution slide # 11
......Structure slide # 16
......Participants slide # 16
......Collaborations slide # 16


Doc 5, Singleton Slide # 1

References


Design Patterns: Elements of Resuable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison Wesley, 1995
Doc 5, Singleton Slide # 2

Singleton

Intent


Insure a class only has one instance, and provide a global point of access to it

Motivation


There are times when a class can only have one instance

Applicability


Use the Singleton pattern when



Doc 5, Singleton Slide # 3
Situations for Using a Singleton

Java Security manager
All parts of a program must access the same security manager

Once set a security manager cannot be changed in a program

Logging the activity of a server

All parts of the server should use the same instance of the logging system

The server should not be able to change the instance of the logging system was it has been set

Doc 5, Singleton Slide # 4
Implementation
Java

// Only one object of this class can be created
class Singleton
     {
     private static Singleton _instance = null;

     private Singleton()     { fill in the blank }

     public static Singleton getInstance()
          {
          if (  _instance == null )
                _instance = new Singleton();
          return _instance;
          }
     public void otherOperations() { blank; }
     }

class Program
     {
     public void aMethod()
          {
          X = Singleton.getInstance();
          }
     }
     


Doc 5, Singleton Slide # 5

Implementation

C++

// Only one object of this class can be created
class Singleton
     {
     private:
          static Singleton* _instance;
          void otherOperations();

     protected:
          Singleton();

     public:
          static Singleton* getInstance();
     }

 Implementation

Singleton*  Singleton::_instance = 0;

Singleton* Singleton::getInstance()
     {
     if (  _instance == 0 )
           _instance = new Singleton;
     return _instance;
     }


Doc 5, Singleton Slide # 6

Singleton and Inheritance



Situation 0

Singleton has subclasses

Each subclass needs to be a singleton

A program can have one copy of each class

Solution

Just make each subclass a singleton


Doc 5, Singleton Slide # 7
Situation 1


Singleton has subclasses

A program can have one copy of an object created of from Singleton or its subclasses

The Easy Part

How to get Singleton to return subclass objects



Singleton* Singleton::getInstance()
     {
     if (  _instance == 0 )
           _instance = new SingletonSubclass;
     return _instance;
     }


Doc 5, Singleton Slide # 8
The Hard Part

How insure that Singleton has the correct subclass object

C++ Solution 1


Singleton's getInstance does the selection based on some global information such as environment, command line option, or a configuration file

Singleton* Singleton::getInstance()
     {
     if (  _instance == 0 )
          {
          const char* singletonStyle = getenv( "singletonStyle" );

          if ( strcmp( singletonStyle, "A" ) == 0 )
                _instance = new A;

          else if ( strcmp( singletonStyle, "B" ) == 0 )
                _instance = new B;

          else
                _instance = new Singleton;
          }

     return _instance;
     }

Problem: Parent class needs to be modified each time a new subclass is implemented
Doc 5, Singleton Slide # 9
The Hard Part

C++ Solution 2 - Registry


class Singleton
     {
     private:
          static Singleton* _instance;

          static ListOfSingletonNamePairs _registry;
          static Singleton* getSingletonFromName( char* name);

     protected:
          Singleton();
          
     public:
          static Singleton* getInstance();
          static void Register( char* name, Singleton* registerer);
          void otherOperations();
     }

Singleton* Singleton::getInstance()
     {
     if (  _instance == 0 )
          {
          const char* singletonName = getenv( "singletonStyle" );
           _instance = getSingletonFromName(singletonName);
     return _instance;
     }


Doc 5, Singleton Slide # 10
The Hard Part
C++ Solution 2 - Registry Continued

How does subclass register with Singleton?

Have the subclass constructor register!

A::A()
     {
     Singleton.Register( "A", this );
     }


How is the subclass constructor called?


Create a static instance of subclass in file that contains the subclass implementation


static A theSingleton;



Doc 5, Singleton Slide # 11
Singleton and Inheritance

The Hard Part - Java Solution


Java does not have getenv, but can use command line arguments and configuration files

Java can not create a static instance of subclass in file that contains the subclass implementation

Protection level problem with constructor

Classes in the same package can access protected constructors

If subclass makes constructor private than even parent can not access child's constructor

Solution 1

Use Class.forName(), static block, and registry

Keeping Singleton classes in different package from clients allows constructors to be protected

Will give solution assuming constructors must be private
Solution when constructors can be protected is simpler


Doc 5, Singleton Slide # 12
Class.forName


class Example
     {
     public String toString()
          {
          return "This is a simple class";
          }
     }

class Test
     {
     public  static  void  main( String  args[] ) throws Exception
          {
          Class which = Class.forName( "Example" );
          Object whichOne = which.newInstance();
          System.out.println( whichOne.toString() );
          }
     }

Output
This is a simple class


Doc 5, Singleton Slide # 13
Java Solution part 1A
abstract class Singleton
     {
     private static Singleton _instance = null;
     
     public static void setInstance( Singleton registerer)
          {
          if ( _instance != null )
               _ instance =registerer ;
          }

     public static void setInstance( String className )
          {
          Class aSingleton = Class.forName( className );

          if ( isSubclassOfSingleton( aSingleton ) )
               {
               Class[] noArgs = new Class[0];
               Method register = 
                         aSingleton.getMethod( "register", noArgs );

               register.invoke( null, noArgs);
               }
          }

     public static Singleton getInstance()
          {
          if (  _instance == null )
                    _instance = getDefaultSingleton(); 
                         
          return _instance;
          }
     }


Doc 5, Singleton Slide # 14
Java Solution part 1B

class Child extends Singleton
     {
     public static void register()
          {
          Singleton.setInstance(  new Child() );
          }
          
     private Child()
          { 
          what ever you need to do;
          }
     }


Doc 5, Singleton Slide # 15
Java Solution part 2

What replaces C/C++ getenv?

Answer - Properties

Persistent properties class. This class is basically a hashtable that can be saved/loaded from a stream. If a property is not
found, a property list containing defaults is searched. This allows arbitrary nesting.


Doc 5, Singleton Slide # 16

Structure




Participants


Singleton

Defines an getInstance operation that lets clients access its unique instance

May be responsible for creating its own unique instance

Collaborations


Clients access a Singleton instance solely through Singleton's getInstance operation

Consequences



visitors since 12-Feb-98