Yavor Atanasov web portfolio

Weblog

2010
05.01

PHP Singleton Design PatternIn software engineering, patterns simply suggest possible solution templates for re-occurring programming challenges. Patterns are not associated with any specific programming language. They just suggest a solution blueprint that can be implemented in any language. Depending on the level at which they operate within the application, software patterns can be divided into design patterns and architectural patterns.

Architectural Patterns operate on a higher level and define the entire system structure and work-flows. An example of an architectural pattern, extremely common in web development, is the Model-View-Controller pattern.

Design Patterns dwell on a lower level and define the relationships and interactions of classes and objects. In object-oriented programming (OOP) design patterns help developers address challenges associated, for instance, with responsibility and polymorphism. Responsibility (single responsibility principle) deals with delegating specific tasks (responsibilities) to specific objects. It makes sure that there is exactly one object dealing with a given task. Polymorphism makes it possible to create a uniform interface to handle values of different data types. In other words, you can alter a given class without changing the rest of the code that interacts with it. This results in more flexible and portable applications with loosen interdependencies.

Two of the most commonly used design patterns with PHP are the Singleton and Factory patterns. The Singleton pattern is a responsibility pattern and the Factory pattern facilitates implementing polymorphism.

The Singleton Pattern in PHP

The Singleton pattern ensures that at any given time there will be just one instance of a given class within the application. It accomplishes that by limiting the object instantiation to just a single point within the object itself. In addition, it restricts its public constructor (by declaring it private) and also blocks the possibility of object cloning (by creating a blank private __clone() method). Thus a singleton class can only initialise itself and no other class can create a new instance or a copy of the object. The singleton class can provide a reference to its only instance if another object requires it.

The following hypothetical situation and sample code illustrate the purpose of the Singleton pattern.

Imagine a class of 4 students. Each student has one responsibility when the class starts – he/she must shout out loud his/her name for their teacher to write down in his attendance book.

Below is some sample code that implements the described task in the conventional way. Two classes are declared – Teacher and Student. The Teacher class has one protected property $_name and two public methods – one is the constructor and the other one marks a student as present. There is also another property $_number_of_instances which is static and it is just for the sake of keeping track of how many instances of the class are created. The Student class has two properties – the name of the student and the student’s teacher. Naturally, it has one public constructor and a public method shoutYourName that needs to tell the teacher that the student is present.

One thing to notice is that every time a student object is instantiated, a brand new teacher object is created as well. In other words, every student in this class has his/her own teacher. Going further down the sample code, four students are created and then they inform their teacher(s) of their presence.

<?php
/**
 Example of conventional implementation
 */

class Teacher {
    private $_name;
    static $_number_of_instances = 0;
    public function  __construct() {
        //initialise the object
        $this->_name = ‘James Hetfield’;
        self::$_number_of_instances ++;
        echo ‘number of teachers:’ . self::$_number_of_instances . ‘<br/>’;
    }
    public function takeAttendance($studentName) {
        //mark the student as present (insert to database)
        echo $studentName . ‘ is present.<br/>’;
    }
}
class Student{
    private $_name;
    private $_teacher; //the teacher of the student
    public function  __construct($name) {
        //create a student
        $this->_name = $name;
        $this->_teacher = new Teacher();
    }
    public function shoutYourName(){
        $this->_teacher->takeAttendance($this->_name);
    }
}
$kirk = new Student(‘Kirk’);
$lars = new Student(‘Lars’);
$robert = new Student(‘Robert’);
$jason = new Student(‘Jason’);
$kirk->shoutYourName();
$lars->shoutYourName();
$robert->shoutYourName();
$jason->shoutYourName();

The code has the following output:

number of teachers:1
number of teachers:2
number of teachers:3
number of teachers:4
Kirk is present.
Lars is present.
Robert is present.
Jason is present.

The picture below illustrates the result of the conventional implementation. It creates multiple unnecessary objects that do the same thing essentially (moreover, it does not recreate the described plot of 4 students and only 1 teacher).

illustration of the conventional implementation

This is where the Singleton pattern comes into play. Below you can see a rewrite of the sample code. The Teacher class has been modified to become a, what is called, Singleton class. The modifications are as follows:

  • Another static property has been added $_instance that will hold the self-created instance of the class.
  • The constructor method was changed from public to private, restricting its access from the outside.
  • A private method __clone() has been declared (doing nothing) to overwrite the PHP magic method __clone() in order to prevent object cloning
  • A public static method getInstance() has been created. Its function is to check if there is already an instance of the class, if there is not it creates one, stores it in the static $_instance variable and finally returns it to whoever requested it.
  • The Student object gets a reference to the teacher’s instance by calling the Teacher::getInstance method.
<?php
/**
 Example of Singleton Pattern implementation
 */

class Teacher {
    private $_name;
    static $_instance;
    static $_number_of_instances = 0;
    private function  __construct() {
        //initialise the object
        $this->_name = ‘James Hetfield’;
        self::$_number_of_instances ++;
        echo ‘number of teachers:’ . self::$_number_of_instances .‘<br/>’;
    }
    private function  __clone() {
        //do nothing (this overwrites the special PHP method __clone())
    }
    public static function getInstance() {
        if(!(self::$_instance instanceof self)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    public function takeAttendance($studentName) {
        //mark the student as present (insert to database)
        echo $studentName . ‘ is present.<br/>’;
    }
}
class Student{
    private $_name;
    private $_teacher; //the teacher of the student
    public function  __construct($name) {
        //create a student
        $this->_name = $name;
        $this->_teacher = Teacher::getInstance();
    }
    public function shoutYourName(){
        $this->_teacher->takeAttendance($this->_name);
    }
}
$kirk = new Student(‘Kirk’);
$lars = new Student(‘Lars’);
$robert = new Student(‘Robert’);
$jason = new Student(‘Jason’);
$kirk->shoutYourName();
$lars->shoutYourName();
$robert->shoutYourName();
$jason->shoutYourName();

The code outputs the following:

number of teachers:1
Kirk is present.
Lars is present.
Robert is present.
Jason is present.

The picture below shows the result. As you can see, using the Singleton pattern, the Teacher class has been instantiated just once and then each Student object receives a reference of that instance.

illustration of the singleton implementation

Benefits of the Singleton Pattern

The Singleton pattern prevents memory duplication and, therefore, saves system resources. In addition, using the Singleton pattern, you can be sure that there is only one flow path for a certain task or data. This results in more controlled and secure application work flow as well as easier debugging and maintenance.

singleton design pattern illustration

Further reading:

4 comments so far

Add Your Comment
  1. Excellent execution of an explanation, covering both implementation and understanding of overall concept for practical use. I was struggling with this concept(deer-in-the-headlights moment!) yesterday trying to come to terms with on object storing an instantiated version within itself(kind of). I finally figured it out and then found this, wish i had found it sooner…

  2. I’m glad it helped :) Soon I might write one on the Factory pattern. If I have time at hand. Greetings

    Yavor

  3. This is perfect! I wrote a text describing this but my supervisor wanted me to use a diagram instead. I thought of such a diagram in my mind but I just wanted to double check and I landed here. Your explanation of Design and Architechural patterns perfectly falls in line with what I was also taught.

  4. the best explanition on the net I found. Thank you

Your Comment