1.7. Одиночка (Singleton)

Это считается анти-паттерном! Для лучшей тестируемости и сопровождения кода используйте Инъекцию Зависимости (Dependency Injection)!

1.7.1. Назначение

Позволяет содержать только один экземпляр объекта в приложении, которое будет обрабатывать все обращения, запрещая создавать новый экземпляр.

1.7.2. Примеры

  • DB Connector для подключения к базе данных

  • Logger

  • Config Manager

  • Threads Handling

  • Блокировка файла в приложении (есть только один в файловой системе с одновременным доступом к нему)

1.7.3. Диаграмма UML

Alt Singleton UML Diagram

1.7.4. Код

Вы можете найти этот код на GitHub

Singleton.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Singleton;
 6
 7use Exception;
 8
 9final class Singleton
10{
11    private static ?Singleton $instance = null;
12
13    /**
14     * gets the instance via lazy initialization (created on first usage)
15     */
16    public static function getInstance(): Singleton
17    {
18        if (self::$instance === null) {
19            self::$instance = new self();
20        }
21
22        return self::$instance;
23    }
24
25    /**
26     * is not allowed to call from outside to prevent from creating multiple instances,
27     * to use the singleton, you have to obtain the instance from Singleton::getInstance() instead
28     */
29    private function __construct()
30    {
31    }
32
33    /**
34     * prevent the instance from being cloned (which would create a second instance of it)
35     */
36    private function __clone()
37    {
38    }
39
40    /**
41     * prevent from being unserialized (which would create a second instance of it)
42     */
43    public function __wakeup()
44    {
45        throw new Exception("Cannot unserialize singleton");
46    }
47}

1.7.5. Тест

Tests/SingletonTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Singleton\Tests;
 6
 7use DesignPatterns\Creational\Singleton\Singleton;
 8use PHPUnit\Framework\TestCase;
 9
10class SingletonTest extends TestCase
11{
12    public function testUniqueness()
13    {
14        $firstCall = Singleton::getInstance();
15        $secondCall = Singleton::getInstance();
16
17        $this->assertInstanceOf(Singleton::class, $firstCall);
18        $this->assertSame($firstCall, $secondCall);
19    }
20}