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.
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
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
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
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
.
$logger = SimpleLogger.new
# But there is nothing to prevent some misguided code from changing it:
$logger = LoggerThatDoesSomethingBad.new