An Elegant Way To Implement The Singleton Pattern

by Finnian Reilly (modified: 2019 Aug 08)

Introduction

I have been trying to find an elegant way to implement the singleton pattern for ages. The main window of a GUI application is a classic example. Now finally I came up with a way I am happy with. Specifically I wanted a way to create an object naturally in an application, and then for the object to make itself available as a shared instance to the rest of the application without first having to call the object from a once function. The latter method I would call an "unnatural way", for want of a better term.

The Solution

The problem is solved by introducing two classes: EL_SHARED_SINGLETONS and EL_SINGLETON. They are used in the following way:

Make a call to routine {EL_SINGLETON}.put_singleton from within the class you wish to share as a global instance:

class MY_CLASS inherit EL_SHARED_SINGLETONS feature {NONE} -- Initialization make do put_singleton (Current) .. end

then define the shared once function as follows:

deferred class SHARED_GLOBAL_INSTANCE inherit EL_ANY_SHARED feature {NONE} -- Constants Global_instance: MY_CLASS local l: EL_SINGLETON [MY_CLASS] once ("PROCESS") create l Result := l.singleton end end

Now just make sure to call the make routine of MY_CLASS before any calls to Global_instance. But in case you call Global_instance to soon, there is a contract to warn you, and it will also throw a helpful exception even when assertions are omitted from the build.

Class EL_ANY_SHARED by the way, is just a convenience class for easy inheritance. Routines copy, default_create, is_equal and out are left undefined.