Share This Article
The singleton pattern in Ruby ensures that only one object (the singleton) can be instantiated from a class.
It is useful to ensure that only one object has a certain state or represents a certain concept in your application.
For example, the Database class could be a singleton to ensure only one database connection.
The logger class could also be a singleton to make sure there is only one logger object in your application.
You can achieve this by adding a private new
method to your class, so that the new
] method can’t be called from outside the class.
class Database
private_class_method :new
def self.instance
@instance ||= new
end
end
The first time the Database.instance
method is called, it will create a new object using the new
method.
The second time it is called, it will use the cached object.
This is a very simple implementation of the singleton pattern in ruby.
Using the Singleton Module
If you just need a basic implementation of the singleton pattern, you can include the Singleton
module in your class instead of implementing it yourself.
This is what the Database
class would look like if you included the Singleton
module:
require 'singleton'
class Database
include Singleton
# rest of the class...
end
Lazy Initialization
One advantage of using the singleton pattern is that you can achieve lazy initialization.
Lazy initialization is when you don’t create the object until the first time it is needed.
This is helpful when you have an object that is expensive to create (i.e. takes a long time to initialize).
For example, if you have a Database class that needs to connect to a database when it is first instantiated, you may want to do lazy initialization so that the database connection is not created until it is needed.
This can be achieved by adding a lazy
keyword before the initialize
method like this:
class Database
attr_reader :connection
def initialize
@connection = nil
end
def connect
@connection = 'connected!'
end
def connected?
@connection == 'connected!'
end
end
When you first create the Database class, it won’t have a connection.
You can create the connection when you need it by calling the connect
method.
You can check if the database is connected by using the connected?
method.
The Module#attr_reader Method
You can access the value of an instance variable by using the instance_variable_get method like this:
db = Database.new
db.instance_variable_get :@connection
# => nil
But this is not very convenient, so you can use the attr_reader
method to create a reader method for the specified instance variable.
In the example above, the attr_reader
method creates a connection
reader method like this:
db = Database.new
db.connection
# => nil
This is much more convenient, so the attr_reader
method is used in most Ruby classes when an instance variable needs to be read.
Summary
In this article, you’ve learned how to implement the singleton pattern in Ruby.
You’ve also learned about the Singleton
module and how it can be used as a drop-in replacement for a custom implementation.
You’ve also learned to achieve lazy initialization with the lazy
keyword and the attr_reader
method.