Let the class of the singleton object manage the creation and access to its sole instance. There are two characteristics that make a singleton: A singleton class has exactly one instance, and access to that one instance is available globally. Using class methods and variables, we can easily build the “classic” implementation of the singleton, the one recommended by the GoF.

A First Try at a Ruby Singleton

Managing the Single Instance

The SimpleLogger class is responsible for managing its single instance. So how would you turn SimpleLogger into a singleton?

class SimpleLogger
  @@instance = SimpleLogger.new

  def self.instance
    return @@instance
	end 
end

# We can now call the SimpleLogger class any number of times and 
# always get back the same logger object:
logger1 = SimpleLogger.instance   # Returns the logger
logger2 = SimpleLogger.instance   # Returns exactly the same logger

Making Sure There Is Only One

Remember, one requirement of the singleton is to ensure that the one and only singleton is the sole instance of the singleton class. So how do we go about securing SimpleLogger against promiscuous instantiation?

class SimpleLogger
  @@instance = SimpleLogger.new
  
	def self.instance
    return @@instance
	end

  **private_class_method :new**
end

The Singleton Module (recommend)

It does all of the heavy lifting of creating the class variable and initializing it with the singleton instance, creating the class-level instance method, and making new private. All we need to do is include the module. From the outside, this new Singleton module-based logger looks exactly like our previous hand-built implementations: Just call SimpleLogger.instance to retrieve the instance and off you go.

require 'singleton'

class SimpleLogger
	include Singleton
end

logger1 = SimpleLogger.instance   # Returns the logger
logger2 = SimpleLogger.instance   # Returns exactly the same logger

Lazy and Eager Singletons

As a consequence, our singleton instance is created before any client code ever gets a chance to call SimpleLogger.instance. Creating the singleton instance before you actually need it is called **eager instantiation—**we just can’t wait to make the thing. The Singleton module, by contrast, waits until someone calls an instance before it actually creates its singleton. This technique is known as lazy instantiation.

Alternatives to the Classic Singleton

Global Variables / Constant as Singletons

$logger = SimpleLogger.new

# But there is nothing to prevent some misguided code from changing it:

$logger = LoggerThatDoesSomethingBad.new