##
# This files shows some possible implementations of the Singleton pattern
# in Ruby. I'm not a huge fan of the Singleton pattern, but it's nice
# in some cases. In this file I'm going to implement a simple logger.
#
##
# The first implementation that can come to our minds is to create a class
# that holds an instance as a class variable that can be accessed through
# the instance method called 'instance'. Then, with this instance you can
# log as usual. Furthermore, the 'new' class method is kept private to prevent
# the programmer of instantiating new logs.
class Log
def initialize
@log = File.new 'log.txt', 'a'
end
def log(msg)
@log.puts msg
end
@@instance = Log.new
def instance
@@instance
end
private_class_method :new
end
##
# We can also achieve the above implementation by including the
# Singleton module.
require 'singleton'
class IncludedSingletonLog
include Singleton
def initialize
@log = File.new 'log.txt', 'a'
end
def log(msg)
@log.puts msg
end
end
##
# And here is a more basic implementation. Here I want to show the idea of
# eager instantiation (which also applies to the techniques used above).
# Eager instantiation means that the instance is created when the class gets
# loaded, even if it's not used.
class EagerLog
@@log = File.new 'log.txt', 'a'
def self.log(msg)
@@log.puts msg
end
private_class_method :new
end
##
# On the other hand, lazy instantiation means that the instance is created
# only when the programmer wants to use this class for the first time.
class LazyLog
def self.log
@@log ||= File.new 'log.txt', 'a'
@@log.puts msg
end
private_class_method :new
end
##
# In Ruby, the difference between a Module and a Class is just three methods:
# :new, :allocate and :superclass. So a Module is almost the same as a Class
# but it cannot be instantiated. Cool, we now can implement the above classes
# as modules but without calling the private_class_method method.
module ModuleLog
@@log = File.new 'log.txt', 'a'
def self.log(msg)
@@log.puts msg
end
end