singleton pattern in ruby
The singleton pattern in ruby:
A class in object oriented programming is a blueprint of entities that needs to be represented. Sometimes when in a program, a certain scenario presents itself where we have to only create one instance of a class and that instance only. This is known as singleton design pattern.
Singleton design pattern eliminates the option of being able to instantiate more than one object. Although the implementation of singleton pattern being a bad design pattern is up for debate, here’s how ruby implements the design pattern.
- One way is to make the new method of a class private
- We can also define a class method named instance that returns the unique instance for the class.
Ruby standard library also comes with a Singleton module that we can include in any class.
- Ruby singleton pattern without using Singleton module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Log def initialize @log = File.new 'log.txt', 'a' end def log(msg) @log.puts msg end @@instance = Log.new def self.instance //method instance should be static @@instance end private_class_method :new end
- Including Singleton module in a class:
The Singleton module contains all the logic to implement the singleton pattern within a class. We have to require the ‘singleton’ library.
1 2 3 4 require 'singleton' class Shop include Singleton end
Now if we try to create a Shop object with Shop.new we’ll see this:
1 2 Shop.new # NoMethodError: private method `new' called for Shop:Class
And if we want to get the one & only Shop object we can use the instance method:
1 2 3 4 Shop.instance.object_id # 5659218 Shop.instance.object_id # 5659218
A new method called instance is added to the Shop class as an instance method. This method always returns the same instance of the Shop class.
In the above example, we can create new Shop objects by using the Shop.send(:new) method.
When the Singleton module is included then the Shop.new method becomes private. This gives the illusion that the Shop class is not instantiable. The problem is that the Object#send method is able to call private methods of a given class.
There is also a method with which we create an instance as soon as the class is loaded, even if it is not used.
1 2 3 4 5 6 7 8 9 class EagerLog @@log = File.new 'log.txt', 'a' def self.log(msg) @@log.puts msg end private_class_method :new end
Likewise, a class can be lazily instantiated, ie, an instance is created in an event the programmer wants to use the class for the first time.
1 2 3 4 5 6 7 8 class LazyLog def self.log @@log ||= File.new 'log.txt', 'a' @@log.puts msg end private_class_method :new end