require 'singleton' class Aardvark include Singleton endThat's it. Mixing in the Singleton module makes the "new" method private and creates an "instance" method that returns the sole instance of Aardvark. (So you'd access the Aardvark by saying "Aardvark.instance".) It also takes care of thread safety.
For educational purposes, this is how you would implement it without the use of the standard library:
class Aardvark private_class_method :new @@instance = new def Aardvark.instance @@instance end endOr, if you want it to be lazy-loading:
class Aardvark private_class_method :new def Aardvark.instance @@instance = new unless @@instance @@instance end end
The following is an implementation of a module (MixIn) that will turn a class into a thread-safe, lazy-loading singleton.
module ThreadSafeSingleton def self.append_features(clazz) require 'thread' clazz.module_eval { private_class_method :new @instance_mutex = Mutex.new def self.instance @instance_mutex.synchronize { @instance = new unless @instance @instance } end } end end # For further educational enjoyment, the following provides a test for # thread-safeness and a contrasting non-thread-safe implementation require 'test/unit' module SimpleSingleton def self.append_features(clazz) clazz.module_eval { private_class_method :new def self.instance @instance = new unless @instance @instance end } end end class SimpleSingletonClass include SimpleSingleton def initialize sleep 1 end end class ThreadSafeSingletonClass include ThreadSafeSingleton def initialize sleep 1 end end class TestSingleton < Test::Unit::TestCase def testSimpleIsNotThreadSafe threads = Array.new(101) { Thread.new { SimpleSingletonClass.instance }} assert(threads.collect { |t| t.value }.uniq.size > 1) end def testThreadSafeIsThreadSafe threads = Array.new(101) { Thread.new { ThreadSafeSingletonClass.instance }} assert_equal(1, threads.collect { |t| t.value }.uniq.size) end end
Compare with PerlSingleton and PythonSingleton