1.7. Одиночка (Singleton)
Это считается анти-паттерном! Для лучшей тестируемости и сопровождения кода используйте Инъекцию Зависимости (Dependency Injection)!
1.7.1. Назначение
Позволяет содержать только один экземпляр объекта в приложении, которое будет обрабатывать все обращения, запрещая создавать новый экземпляр.
1.7.2. Примеры
DB Connector для подключения к базе данных
Logger
Блокировка файла в приложении (есть только один в файловой системе с одновременным доступом к нему)
1.7.3. Диаграмма UML

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}