in this article we’re going to explore the following topics:

the singleton pattern

the Singleton module

module lazy loading

Before to start

I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1

Please feel free to spread the word and share this post! 🙏

Thank you for your time!

The singleton pattern

As a class is only a blueprint, developers prefer to deal with objects. In effect, objects are the in-memory representation of a class. An object encapsulates data and behaves as the class defines it. There is no restriction concerning the number of objects that can be created for a given class.

Ok. That’s cool.

But sometime, the system requires only one instance of a class to coordinate actions across the program. So we’d like to ensure that only one instance of a given class exists for a running program. That’s when the singleton pattern intervenes. The singleton pattern is a design pattern that restricts the instantiation of a given class to one object.

Let’s see how Ruby deals with this design pattern

The Singleton module

The Singleton module contains all the logic to implement the singleton pattern within a class

As the Singleton module isn’t part of the Ruby’s Core Library, we have to require the 'singleton' library. This library contains the Singleton module definition.

Then we define a Config class that includes the Singleton module. At this moment a new method called instance is added to the Config class. This method always returns the same instance of the Config class. As we can see, a call to the Config.new method raises a NoMethodError .

So, by including the Singleton module, the Config class can only access to a uniq instance of this class via the Config.instance method.

Well. This is not exactly true

In the above example, we can create new Config objects by using the Config.send(:new) method.

How is it possible ?

When the Singleton module is included then the Config.new method becomes private. This gives the illusion that the Config class is not instantiable. The problem is that the Object#send method is able to call private methods of the receiver — Config in our case.

So be aware of this when you use the Singleton module.

NB: feel free to have a look to the Private & Protected in Ruby article if you’re unfamiliar with the private keyword in Ruby.

Lazy loading

Let’s have a look to how the Singleton.instance method works

Here we can see that including the Singleton module within the Lazy class doesn’t automatically create a uniq instance of this class. Indeed, the uniq instance of the Lazy class is only created once at the first call of Lazy.instance . This instance is then always returned by Lazy.instance .

We can make sure that this method behaves as expected by calling ObjectSpace.each_object(Lazy){} . This method returns the number of existing objects for a given class — in our case the Lazy class.

So, before the call to Lazy.instance , there is no Lazy object instantiated. Then, after the call to Lazy.instance , we notice that there is one Lazy object in our program. Finally, when we call Lazy.instance for the second time then we can see that there is still only one Lazy object in our program.

In the part II, we’re going to talk about the Singleton module with inheritance and with the clone and dup methods.

Voilà !

May I have your attention please 🎤🎤

Feel free to subscribe here: www.rubycademy.com