SDSU CS 696: Advanced OO
Spring Semester, 1997
Doc 9, Design Patterns

To Lecture Notes Index
San Diego State University -- This page last updated Mar 4, 1997
----------

Contents of Doc 9, Design Patterns

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

Doc 9, Design Patterns Slide # 1

References


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

Design Patterns

What is a Pattern?

"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice"

Christopher Alexander


A pattern has four essential elements

Pattern name

Problem

Solution

"the pattern provides an abstract description of a design problem and a general arrangement of elements solves it"

Consequences

Doc 9, Design Patterns Slide # 3

Purpose
ScopeCreationalStructuralBehavioral
ClassFactory MethodAdapterInterpreter
Template Method
ObjectAbstract factory
Builder
Prototype
Singleton
Adapter
Bridge
Composite
Facade
Flyweight
Proxy
Chain of Responsibility
Command
Iterator
Mediator
Memento
State
Strategy
Visitor


Doc 9, Design Patterns Slide # 4

OMT-Based Notation Examples from Text


Class Diagram



Object Diagram



Inheritance


Doc 9, Design Patterns Slide # 5
OMT-Based Notation Examples from Text

Abstract and Implementation




Class Relations




Creating


Doc 9, Design Patterns Slide # 6
OMT-Based Notation Examples from Text

Object Interaction



Doc 9, Design Patterns Slide # 7

Design Principle 1


Program to an interface, not an implementation

Use abstract classes (and/or interfaces in Java) to define common interfaces for a set of classes

Declare variables to be instances of the abstract class not instances of particular classes


Benefits of programming to an interface



Doc 9, Design Patterns Slide # 8
Programming to an Interface - Example





class A 
     {
     DateServer myServer;

     public operation()
          { myServer.someOp(); }
     }

class B 
     {
     ServerEngine myServer;

     public operation()
          { myServer.someOp(); }
     }

Doc 9, Design Patterns Slide # 9

Design Principle 2


Favor object composition over class inheritance


Composition

Allows behavior changes at run time

Helps keep classes encapsulated and focused on one task

Reduce implementation dependencies


Doc 9, Design Patterns Slide # 10

Designing for Change


Some common design problems with design patterns that address the problem


Doc 9, Design Patterns Slide # 11

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 9, Design Patterns Slide # 12
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 9, Design Patterns Slide # 13

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 9, Design Patterns Slide # 14

Singleton and Inheritance

The Problem

Subclass Singleton and have Singleton return subclass objects


The Easy Part

How to get Singleton to return subclass objects



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


Doc 9, Design Patterns Slide # 15
Singleton and Inheritance
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 or configuration file

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;
     }

Problem: Parent class needs to be modified each time a new subclass is implemented
Doc 9, Design Patterns Slide # 16
Singleton and Inheritance
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 9, Design Patterns Slide # 17
The Hard Part
C++ Solution 2 - Registry Continued

How does subclass register with Singleton?

Have the subclass constructor register!

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


How is the subclass constructor called?


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


static SingletonLeftChild theSingleton;


Doc 9, Design Patterns Slide # 18
Singleton and Inheritance

The Hard Part - Java Solution


Java does not have getenv

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

A Solution

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

Java 1.1 has a simpler solution


Doc 9, Design Patterns Slide # 19
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 9, Design Patterns Slide # 20
Java Solution part 1A
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;
          }
     }


Doc 9, Design Patterns Slide # 21
Java Solution part 1B

class Child extends Singleton
     {
     static
          {
          Singleton.register( "Child", new Child() );
          }
          
     private Child()
          { 
          System.out.println( "child is born");
          }
     }


Doc 9, Design Patterns Slide # 22
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 9, Design Patterns Slide # 23

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


----------