单例模式

单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。

  • 将默认构造函数设为私有,防止其他对象使用单例类的 new运算符。
  • 新建一个静态构建方法作为构造函数。该函数会 “偷偷” 调用私有构造函数来创建对象,并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
class Singleton
{
private static $instances = [];

protected function __construct(){}

protected function __clone(){}

public function __wakeup()
{
throw new \Exception("Cannot unserialize singleton");
}

public static function getInstance()
{
$subclass = static::class;
if (!isset(self::$instances[$subclass])) {
self::$instances[$subclass] = new static();
}
return self::$instances[$subclass];
}
}

class Logger extends Singleton
{

private $fileHandle;

protected function __construct()
{
$this->fileHandle = fopen('php://stdout', 'w');
}

public function writeLog(string $message): void
{
$date = date('Y-m-d');
fwrite($this->fileHandle, "$date: $message\n");
}

public static function log(string $message): void
{
$logger = static::getInstance();
$logger->writeLog($message);
}
}

class Config extends Singleton
{
private $hashmap = [];

public function getValue(string $key): string
{
return $this->hashmap[$key];
}

public function setValue(string $key, string $value): void
{
$this->hashmap[$key] = $value;
}
}

/**
* The client code.
*/
Logger::log("Started!");

// Compare values of Logger singleton.
$l1 = Logger::getInstance();
$l2 = Logger::getInstance();
if ($l1 === $l2) {
Logger::log("Logger has a single instance.");
} else {
Logger::log("Loggers are different.");
}

// Check how Config singleton saves data...
$config1 = Config::getInstance();
$login = "test_login";
$password = "test_password";
$config1->setValue("login", $login);
$config1->setValue("password", $password);
// ...and restores it.
$config2 = Config::getInstance();
if (
$login == $config2->getValue("login") &&
$password == $config2->getValue("password")
) {
Logger::log("Config singleton also works fine.");
}

Logger::log("Finished!");