Global variables tie classes to context and create unnatural interdependencies in an application. A Singleton ensures that a class only has one instance, and provides a global point of access to it. If a system only needs one instance of a class, and that instance is used in different parts of the system, you can control instantiation and access by making the class a singleton.

The Problem

Global variables are often the bane of modern software development projects. Many classes need to be accessible from anywhere within an application. Classes that encapsulate configuration details, database access, or logging are required throughout an application. But relying on global variables couples the class with the current application, undermining encapsulation and making the class less reusable. If you were to try to use the class in a different context you would need to be sure that the same global variable is available, and properly instantiated.

Rather than creating global variables, well designed object-oriented systems generally pass object instances around via method calls. This has the benefit of making the collaboration explicit: it’s clear that the object depends on the data because it is part of the method’s signature. The problem with this approach is that it sometimes requires you to use classes as a sort of conduit, passing objects around that they never use, and creating unnecessary dependencies.

The Singleton pattern distinguishes itself from normal global variables by inverting the responsibilities of the global data and the client that uses it. With the Singleton pattern, the global class itself is responsible for keeping track of its sole instance. It ensures that multiple instances are not created by intercepting requests to create a new object, and provides a way to access its single instance from anywhere. Collaboration is explicit, because the client retrieves the data from a method of the singleton class. But dependencies are reduced, because classes that are not interested in the global data no longer need to worry about it.

Implementation

To implement the Singleton pattern you need to somehow assert control over object creation. This is actually pretty simple to do in most languages: simply define a private (or protected) constructor. In PHP it looks something like this:

class Configuration {
  private $config = array();

  private function __construct() { }

  public function setOption( $option, $value ) {
    $this->config[$option] = $value;
  }

  public function getOption( $option ) {
    return $this->config[$option];
  }
}

Because the constructor is declared private, client code cannot instantiate an object of the class. We can use a static method and a static property to mediate object instantiation, giving client code access to the global data throughout the application while ensuring that only one instance of the class is ever created:

class Configuration {
  private $config = array();
  private static $instance;

  private function __construct() { }

  public static function getInstance() {
    if( is_null( self::$instance ) ) {
      self::$instance = new self();
    }
    return self::$instance;
  }

  public function setOption( $option, $value ) {
    $this->config[$option] = $value;
  }

  public function getOption( $option ) {
    return $this->config[$option];
  }
}

Because the Configuration::getInstance() method is public and static, it can be called from anywhere in the system that configuration data is required.

Consequences

Like global variables, Singletons can create dependencies that are difficult to find and debug. Normally, dependencies are obvious because they are declared as part of a classes interface (i.e. as arguments to a method). But with the Singleton, dependencies are hidden in the implementation. This can make it difficult to track all of the relationships in a complex system.

That said, the Singleton has many benefits. It can be used for lazy instantiation of objects (i.e. the object is only instantiated when it is first used), as the example above shows, which can be a big benefit for classes that use constrained resource like database connections. It also permits you to limit the number of instances to some number greater than one (sometimes called a Multiton), which can be useful for opening some limited number of I/O streams, for example.

The Singleton pattern is a definite improvement over global variables in an object-oriented system, and moderate use of this pattern can improve the design of a system. Singletons are related to the Abstract Factory, Prototype, and Factory Method patterns which I’ll be discussing in future posts. If you’re interested in learning more about these related patterns, you can subscribe to my feed.