Navigation:  Appendix B: Dolphin Pattern Book > Global Variable Patterns >

Singleton

Previous pageReturn to chapter overviewNext page

Context

When creating a New Class it may be apparent that there should only ever be one instance of it. It's too risky to rely on a developer not to create several instances by accident, so a scheme to enforce this criterion is required. An example might be a class which represents the mouse or screen. There should only be a single representation of these devices since that accurately models the real world situation. We must also provide a means of accessing the singleton; ideally without creating a Global Variable in which to store it.

Solution

Make the class itself responsible for managing its single instance.

Implement this by adding a class variable to hold the singleton, and a class method current to answer it. Ensure that the singleton is initialized, either when the application starts, or by using Class Initialization or Lazy Initialization. All access to the singleton should be by sending #current to the class.

You should also, disable the #new method by overriding it to raise an exception. This will prevent programmers from accidentally creating their own, non-singleton, instances of the class.

Examples

An imaginary Mouse class has a class variable called Current which holds the singleton instance. Access to it is allowed only through the current class method which uses Lazy Initialization.

Mouse class>>current

  "Answer the singleton instance of the Mouse class."

  Current isNil ifTrue: [self current: self basicNew].

  ^Current

 

Mouse class>>current: aMouse

  "Set the Mouse singleton Current to aMouse."

  Current := aMouse

 

Mouse class>>new

  "Mouse is a singleton class. Use #current."

  self shouldNotImplement

 

Consequences

Sometimes you need to create a class which isn't a true singleton, but instead has a commonly used default instance but other instances can potentially exist. In such cases, create the class as if it were a singleton but use #default (by convention) to access the default instance. Don't override #new though, or you won't be able to create any additional instances.

Known Uses

The DesktopView class maintains a singleton instance in the class variable Current, and access to this singleton is provided by the #current class method. DesktopView initializes this during it's Class Initialization.

current

  "Answers the singleton instance of the receiver."

  ^Current

 

current: aDesktopView

  "Sets the singleton instance of the receiver."

  Current := aDesktopView

 

initialize

  "Initialize the DesktopView singleton."

  Current := self new

          assumeDesktopHandle;

          yourself

 

Related Patterns

Global Variable