References | slide # 1 |
Design Patterns | slide # 2 |
...OMT-Based Notation | slide # 4 |
...Design Principle 1 | slide # 7 |
...Design Principle 2 | slide # 9 |
...Designing for Change | slide # 10 |
Singleton | slide # 11 |
...Intent | slide # 11 |
...Motivation | slide # 11 |
...Applicability | slide # 11 |
...Implementation | slide # 13 |
...Singleton and Inheritance | slide # 14 |
......C++ Solution 1 | slide # 15 |
......C++ Solution 2 - Registry | slide # 16 |
......Java Solution | slide # 18 |
...Structure | slide # 23 |
...Participants | slide # 23 |
...Collaborations | slide # 23 |
Problem
Solution
Purpose | |||
Scope | Creational | Structural | Behavioral |
Class | Factory Method | Adapter | Interpreter Template Method |
Object | Abstract factory Builder Prototype Singleton | Adapter Bridge Composite Facade Flyweight Proxy | Chain of
Responsibility Command Iterator Mediator Memento State Strategy Visitor |
Declare variables to be instances of the abstract class not instances of particular classes
Benefits of programming to an interface
class A { DateServer myServer; public operation() { myServer.someOp(); } } class B { ServerEngine myServer; public operation() { myServer.someOp(); } }
Composition
// 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(); } }
// 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; }
Singleton* Singleton::getInstance() { if ( _instance == 0 ) _instance = new SingletonSubclass; return _instance; }
Singleton* Singleton::getInstance() { if ( _instance == 0 ) { const char* singletonStyle = getenv( "singletonStyle" ); if ( strcmp( singletonStyle, "Left" ) == 0 ) _instance = new SingletonLeftChild; else if ( strcmp( singletonStyle, "Right" ) == 0 ) _instance = new SingletonLeftRight; else _instance = new Singleton; } return _instance; }
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; }
Have the subclass constructor register!
SingletonLeftChild::SingletonLeftChild() { Singleton.Register( "SingletonLeftChild", this ); }
Create a static instance of subclass in file that contains the
subclass implementation
static SingletonLeftChild theSingleton;
Java can not create a static instance of subclass in file that contains the subclass implementation
Protection level problem with constructor
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
Java 1.1 has a simpler solution
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() ); } }
abstract class Singleton { private static Singleton _instance = null; private static Hashtable _registry = new Hashtable(); public static void register( String className, Singleton registerer) { _registry.put( className, registerer ); } public static Singleton getInstance() { if ( _instance == null ) try { String childClassName = "Child"; // Insure child's static block registers child Class.forName( childClassName ); _instance = (Singleton) _registry.get( childClassName ); } catch ( ClassNotFoundException wrongName ) { _instance = getDefaultSingleton(); } return _instance; } }Java Solution part 1B
class Child extends Singleton { static { Singleton.register( "Child", new Child() ); } private Child() { System.out.println( "child is born"); } }
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.
Structure