By Tcoch

Singleton : how to implement


Why this article ?

I recently implemented the singleton design pattern to resolve a performance issue, and I though I'd share the experience.
The project I was working on is a full declarative PHP website (like we all did at some point, let's be honest), ... and the client wants it to stay that way.
So, we can forget about nice things from frameworks like Symfony or Laravel: containers, dependency injection, request & response, and so on. But still, in this project, there's a lot of informations stored in the session. OK, so let's make a Session class! We'll handle things properly in there.
class MySession
{
    private array $session;

    public function __construct()
    {
        $this->session = $_SESSION ?? [];
        $this->checkSomethingInTheDatabase();
    }
}
OK, great, but now, each time in need the session (remember, I have a looot of files), I'm going to have to call that class, and perform an action in the database. Mmmh ... The database stuff takes some times, and consume some ressources ... Can't I do this just once?

What's the singleton principle ?

The generic definition is that this ensures that a class has only one instance.
So, if there's one instance only, it also means that my constructor will be called only once! Perfect.

Got it ! Now, how to implement it?

The main idea is :
  • Make the constructor private
  • Create a new attribute in the class type-hinted as the class itself
  • Create a static method, that will return an instance of the class (the only instance in fact)
In PHP, it can be done like this :
class MySession
{
    private array $session;

    private static ?MySession $mySession = null;

    /**
     * Create a private constructor
     */
    private function __construct()
    {
        $this->session = $_SESSION ?? [];
        $this->checkSomethingInTheDatabase();
    }

    /**
     * This static function will handle the creation of a unique instance of MySession
     * The principle is :
     * - If the instance does not exists, it is create by this function
     * - If it exists, it is returned
     * Since the constructor is private, there's no other to create an instance of MySession !
     * This instance is stored directly in $mySession
     *
     * @return MySession
     */
    public static function getInstance(): MySession
    {
        if (null === self::$mySession) {
            self::$mySession = new self();
        }

        return self::$mySession;
    }
}

Use cases

This design pattern can be useful to ensure that only connection to a database is active, or that a file is accessed only by on resource (at least, in your code).
In my case, it ensured that $this->checkSomethingInTheDatabase() was called only once, limiting the number of requests to the database.
Articles

Find a random article based on a tag:
Socials