Sometimes you want to override the default way in which Ruby creates
objects. As an example, let's look at our jukebox. Because we'll have
many jukeboxes, spread all over the country, we want to make
maintenance as easy as possible. Part of the requirement is to log
everything that happens to a jukebox: the songs that are played, the
money received, the strange fluids poured into it, and so on. Because
we want to reserve the network bandwidth for music, we'll store these
logfiles locally. This means we'll need a class that handles logging.
However, we want only one logging object per jukebox, and we want
that object to be shared among all the other objects that use it.
Enter the Singleton pattern, documented in Design
We'll arrange things so that the
only way to create a logging object is to call
and we'll ensure that only one logging object is ever created.
@@logger = nil
@@logger = new unless @@logger
private, we prevent anyone from
creating a logging object using the conventional constructor. Instead, we provide a class method,
. This uses the class variable
keep a reference to a single instance of the logger, returning that
instance every time it is called.[The implementation of
singletons that we present here is not thread-safe; if multiple
threads were running, it would be possible to create multiple logger
objects. Rather than add thread safety ourselves, however, we'd
probably use the
Singleton mixin supplied with Ruby, which is
documented on page 468.]
We can check this by looking
at the object identifiers the method returns.
Using class methods as pseudo-constructors can also make life easier
for users of your class. As a trivial example, let's look at a class
that represents a regular polygon. Instances of
are created by giving the constructor the required number of sides and
the total perimeter.
def initialize(numSides, perimeter)
However, a couple of years later, this class is used in a different
application, where the programmers are used to creating shapes by
name, and by specifying the length of the side, not the
perimeter. Simply add some class methods to
There are many interesting and powerful uses of class methods, but
exploring them won't get our jukebox finished any sooner, so let's