1.7. 单例模式¶
注:单例模式可能被认为是一种“反模式”。为了获得更好的可测试性和可维护性,建议使用依赖注入。
1.7.1. 目标¶
让应用只存在一个对象的实例,处理所有的调用。
1.7.2. 例子¶
- 数据库连接器
- 日志记录器
- 应用程序的锁定文件(Lock file,理论上整个应用应该只有一个锁文件)
1.7.3. UML 图¶

1.7.4. 代码¶
你可以在 GitHub 上找到这些代码
Singleton.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <?php
declare(strict_types=1);
namespace DesignPatterns\Creational\Singleton;
use Exception;
final class Singleton
{
private static ?Singleton $instance = null;
/**
* gets the instance via lazy initialization (created on first usage)
*/
public static function getInstance(): Singleton
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* is not allowed to call from outside to prevent from creating multiple instances,
* to use the singleton, you have to obtain the instance from Singleton::getInstance() instead
*/
private function __construct()
{
}
/**
* prevent the instance from being cloned (which would create a second instance of it)
*/
private function __clone()
{
}
/**
* prevent from being unserialized (which would create a second instance of it)
*/
public function __wakeup()
{
throw new Exception("Cannot unserialize singleton");
}
}
|
1.7.5. 测试¶
Tests/SingletonTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php
declare(strict_types=1);
namespace DesignPatterns\Creational\Singleton\Tests;
use DesignPatterns\Creational\Singleton\Singleton;
use PHPUnit\Framework\TestCase;
class SingletonTest extends TestCase
{
public function testUniqueness()
{
$firstCall = Singleton::getInstance();
$secondCall = Singleton::getInstance();
$this->assertInstanceOf(Singleton::class, $firstCall);
$this->assertSame($firstCall, $secondCall);
}
}
|