SnapShooter Backups Server, Database, Application and Laravel Backups - Get fully protected with SnapShooter

Understanding Design Patterns - Singleton

Ensures a class has only one instance, and provides a global point of access of it.

The health clinic has recently offered free medicines if you come in for a checkup. The promotional stint is working so well, and it is just a matter of time before the front staff will have more patients than they can handle. Everyone was so busy that instead of having an organized waiting room, it was a total chaos. After several days of patients flooding in the receptionist, Anne was frustrated and stressed, she went into the the clinic head's office and blurted, "We need to organize the patients, or we are going to go down the drain".

The head of the clinic called a meeting and asked the staff for suggestions, and they came up with the idea of a ticketing system. The aim was to get the patients organized so that it can ease the front staff's task from doing manual registration.

Let us see how we can help.

Before we do any code design, we need to know the condition and capability of the the health clinic. The clinic has only one physical printer.

We could design our TicketPrinter class similar to:

class TicketPrinter
{
    public $isPaperOut;
    public function __construct()
    {
        $this->isPaperOut = true;
    }
 
    public function printTicket()
    {
        if ($this->isPaperOut) {
            // load more papers into paper
            $this->loadMorePapers();
            $this->isPaperOut = false;
        } else {
            // deduct papers from printer
            $this->minusPaper();
            echo 'print queue number';
        }
    }
}

The printerTicket() method will have to check the paper’s status every time it does the print job. If it runs out of paper, it should automatically load more (let's assume that is possible).

Looks like we need to check the ink’s status too. So let us add that also:

class TicketPrinter {
    public $isPaperOut;
    public $isInkOut;
    public function __construct()
    {
        $this->isPaperOut = true;
        $this->isInkOut = true;
    }
 
    public function printTicket()
    {
        if ($this->isPaperOut) {
            // load more papers into paper
            $this->loadMorePapers();
            $this->isPaperOut = false;
        } else if($this->isPaperOut) {
            // load more papers into paper
            $this->loadMoreInk();
            $this->isInkOut = false;
        } else {
            // deduct papers from printer
            $this->minusPaper();
            // use ink
            $this->deductInk();
            echo 'print queue number';
        }
    }
}

It seems that we have a working TicketPrinter, but before we move on, let us examine the situation again. Since we have only one physical printer in the clinic, what will happen if by accident we create two instances of TicketPrinter class. Because they are using the same shared printer, it will surely cause a big problem.

You may argue that we can always just create another instance of TicketPrinter but how can you make sure everyone follows that? So I propose we use the Singleton pattern in this case.

Let us rework TicketPrinter class a bit:

class TicketPrinter
{
    private static $uniqueInstance=null;
    public $isPaperOut;
    public $isInkOut;
    private function __construct()
    {
        $this->isPaperOut = true;
        $this->isInkOut   = true;
    }
 
    public static function getInstance()
    {
        if (self::$uniqueInstance==null) {
            self::$uniqueInstance = new TicketPrinter();
        }
        return self::$uniqueInstance;
    }
 
    public function printTicket()
    {
    }
}

Because constructor of TicketPrinter has become private it can not be instantiated by constructor as normal. To obtain an instance of TicketPrinter, we instead do:

$ticketPrinter = TicketPrinter::getInstance();

As you can see. Singleton Pattern has ensured that there is only one existence of TicketPrinter’s instance at any point of time across the system.

The end

Hopefully this simple tutorial helped you with your development. If you like our post, please follow us on Twitter and help spread the word. We need your support to continue. If you have questions or find our mistakes in above tutorial, do leave a comment below to let us know.