Singleton variations

I end up using a Singleton pattern from time to time, however in Pharo there are several variations commonly used; each with some subtle differences that may confuse a programmer not familiar with them.


Pure singleton ensuring a single global instance.

When implementing this variation, #new should be blocked.

For example Author (a class holding programmer’s name used for code authoring).

Author class>>uniqueInstance
^ uniqueInstance ifNil: [ uniqueInstance := super new ]
Author class>>new
self error: 'Author is a singleton -- send uniqueInstance instead'

Notice the super new; because #new is blocked, we have to go around it. Alternatively we can use uniqueInstance := self basicNew initialize.


As the name suggests, this returns some meaningful default instance, but there is no reason to bar the user from creating more instances.

For example RPackageOrganizer holds references to all packages in the system, but for testing purposes a limited one might be needed.

Similarly useful for caches or resource-heavy(ish) classes where having a single instance everywhere is ok, such as UUIDGenerator.


Useful if we want to keep the same instance system-wide, but we also want to change it under some circumstances.

Prime example is UITheme which should be the same everywhere (i.e. all widgets should use the same theme), however we can still change the currently active theme.


In addition to the methods above, it is also common to add a #reset method that removes the singleton value. Maybe you want to clean-up a cache or just reset an obsolete reference.


Of course you can always go through the actual implementations in the image:

MessageBrowser browse: (#uniqueInstance implementors select: #isMetaSide).
MessageBrowser browse: (#default implementors select: #isMetaSide).
MessageBrowser browse: (#current implementors select: #isMetaSide).

Based on a mailing list discussion