«

»

May 25

Print this Post

Design patterns: singleton

This month I’d like to write about singleton pattern and tell you how it’s described in Head First: Design Patterns book. This chapter was one of the shortest in the book, so far. I read it a while ago and wanted to post about it earlier but as always… lack of free time didn’t let me do this ;)

Despite the fact we learn about what a singleton is at the beginning, there is still a case study which helps us learn more. This time it’s a chocolate factory! :) We’re presented with a controller class of chocolate boiler in Choc-O-Holic Inc. The class looks like this:

class ChocolateBoiler {
  private $empty;
  private $boiled;

  public function __construct() {
    $this->empty = true;
    $this->boiled = false;
  }

  public function fill() {
    if( $this->isEmpty() ) {
      $this->empty = false;
      $this->boiled = false;
      // fill the boiler with a milk/chocolate mixture
    }
  }

  public function drain() {
    if( !$this->isEmpty() && $this->isBoiled() ) {
      // drain the boiled milk and chocolate
      $this->empty = true;
    }
  }

  public function boil() {
    if( !$this->isEmpty() && !$this->isBoiled() ) {
      // bring the content to a boil
      $this->boiled = true;
    }
  }

  public function isEmpty() {
    return $this->empty;
  }

  public function isBoiled() {
    return $this->boiled;
  }
}

The authors of the code made everything to prevent of happening something bad. Just look at all of the if statements. It’s impossible to fill not an empty boiler, drain an empty boiler or not boiled content and boil an empty boiler or already boiled one. But things might get wrong if there are more ChocolateBoiler instances. That’s why we’re asked to change a little bit the class and use singleton pattern:

class ChocolateBoiler {
  private $empty;
  private $boiled;
  private static $instance = null;

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

    return self::$instance;
  }

  private function __construct() {
    $this->empty = true;
    $this->boiled = false;
  }

  public function fill() {
    if( $this->isEmpty() ) {
      $this->empty = false;
      $this->boiled = false;
      // fill the boiler with a milk/chocolate mixture
    }
  }

  public function drain() {
    if( !$this->isEmpty() && $this->isBoiled() ) {
      // drain the boiled milk and chocolate
      $this->empty = true;
    }
  }

  public function boil() {
    if( !$this->isEmpty() !$this->isBoiled() ) {
      // bring the content to a boil
      $this->boiled = true;
    }
  }

  public function isEmpty() {
    return $this->empty;
  }

  public function isBoiled() {
    return $this->boiled;
  }
}

Now, when anyone tries to create an instance of ChocolateBoiler she’ll have to use ChocolateBoiler::getInstance() method. Otherwise this line of code:

$chocolateBoiler = new ChocolateBoiler();

restults with:

PHP Fatal error:  Call to private ChocolateBoiler::__construct() from invalid context

After that we read the singleton pattern’s definition:

The Singleton Pattern ensures a class has only once instance, and provides a global point of access to it.

And basically the PHP part must end here. Rest of the chapter in the book describes some other issues developers should be aware of when implementing Singleton pattern in Java. The Java application might work in few threads. That means that different code lines might be executed separately. Authors describes few different ways of how to deal with multi-threading in Java.

Last time I’ve checked there were no core multi-threading concepts in PHP. However, you could find lots of solution which described how to simulate it. One of them was even lectured at our polish php event. I left links I’ve found on the Internet about PHP and multi-threading. But recently I’ve read about pthreads which is still an experiment.

Other examples

I didn’t search for it long, therefore I didn’t find any examples of how to implement Singleton in PHP with pthreads used. The only one common thing in the all PHP examples I’ve read is some more PHP magic ;) In the examples above I used __construct() magic function but __clone() and/or __wakeup magic method is commonly used as well:

class SingletonExample {
  public function __clone() {
    trigger_error('Cloning instances of this class is forbidden.', E_USER_ERROR);
  }

  public function __wakeup() {
    trigger_error('Unserializing instances of this class is forbidden.', E_USER_ERROR);
  }
}

Singleton examples

Multi-threading

Other design patterns

Here is the list of described by me design patterns:

Permanent link to this article: https://blog.lukaszewski.it/2013/05/25/design-patterns-singleton/

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>