Singleton Design Pattern

Posted on 06 March, 2018
Whole idea around singleton design pattern is generally simple. It's all about making sure that we always use the same instance of one object through the whole app.

Basic idea

Basic idea behind singleton design pattern is about making sure that we always access some resource through exactly the same provider. Pretty good example for its common use would be when communicating with the database. If we are accessing data in a database, first we need to establish connection and then to fetch a data. Using singleton approach, every time we try to get data, we'll be using same connection that's created on the first call.

Singleton design pattern is breaking SOLID approach, specifically the O which stands for open/close principle

Specs

There is a few common things for every singleton class:

  • They can't be cloned
  • Can't be extended
  • This type of classes can not be instantiated manually using new keyword
  • They are lazy loaded

Implementation

Enough talk, let's jump straight to the code:

File: Singleton.php
// Prevent inheritance with "final" keyword
final class Singleton
{
    // Instance itself will be held here
    private static $instance;

    // Dummy resource manager representation
    private $resourceManager;

    // Every singletone class should have method that returns our singleton instance.
    // If instance does not exists it'll be constructed right here.
    public static function instance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new static();
        }

        return self::$instance;
    }

    // We made constructor private so class can't be instanced manually.
    // Constructor will be called only by "instance()" method of this class.
    private function __construct()
    {
        // Let's pretend that this resource manager is some some expensive data resource.
        // Our resource manager will simply be a random number.
        $this->resourceManager = rand(0, 9);
    }

    // We made clone private so instance can't be cloned
    private function __clone() {}

    public function getData()
    {
        // Get some data over our resource manager.
        // We'll be using our existing, already created resource manager and fetch some data from it.               
        return 'Resource manager ID: ' . $this->resourceManager . ' -> Data: ' . rand(100, 999);
    }
}

Now we have our simple singleton representation of a class. Let's see how to use it.

Every time we want to access our singleton instance we'll be using static instance method, and than chain method we want to use. In this case we'll try to get some data through our resource manager.

echo Singleton::instance()->getData();

This was simple one, but lets take a look into another - same call, somewhere later in the code.

echo Singleton::instance()->getData();

Our output is telling us that we are always getting the same data provider (represented with ID: 3), and only data itself are different.

This is a root principle of singletone design pattern.

Some examples when to use it:

  • environment info (am I currently on dev, production etc.)
  • logging (log messages through the same logger from different part of the app/code)
  • db connection (single connection is established and we just use it to fetch data)

Advantages

  • Singleton classes are lazy loaded (lazy loading is an approach commonly used in computer programming to delay initialization of an object, or getting value from some expensive operation until first time it is needed)
  • Resources saving (prevent multiple instances of the same thing that might occur)

Looking at our example this actually means that instance isn't created at init time, but actually first time method Singleton::instance() is used.

Disadvantages

On the first look everything seems very simple, this is one of the easiest patterns to grasp. As we already saw, it consists of just a few lines of code.

But there is a catch here:

Singleton design pattern is breaking SOLID approach, specifically the O which stands for open/close principle

A class is considered open if we are able to inherit from it. We made our class "final" to be able to prevent inheritance and allow multiple instances of the same object that initially is considered singleton. Since our class is final, this principle is broken.

If we omit final keyword and allow class extension/inheritance, than we can no longer guarantee singleton pattern.


That would be my way of explaining this design pattern as simple as possible. Hope you could learn something from it. If you have any questions or suggestions, please don't hesitate to ask in the comments below.