php 设计模式(一)单例模式与多例模式 | Leezhiy Blog

php 设计模式(一)单例模式与多例模式

定义:简单来说,整个应用中只有一个实例对象的设计模式被称之为单例模式,而多例模式是指存在一个类有多个相同实例,而且该实例都是该类本身。这个类叫做多例类。

注:多例模式被公认为是 反面模式,为了获得更好的可测试性和可维护性,请使用“依赖注入模式”

单例模式与多例模式的要点

多例模式实际上就是单例模式的推广。

单例模式与多例模式的相同点:

构造函数都需要外部不可访问,一般来说标记为 private (防止外部代码使用 new 操作符创建对象),单例类与多例类不能在其他类中实例化,只能被其自身实例化;

拥有一个保存类的实例的静态变量

拥有一个访问这个实例的公共静态方法 (常用 getInstance() 方法进行实例化类,通过比较操作符可以检测到类是否已被实例化)

单例模式与多例模式的不同点:

多例类可以有多个实例而单例类只有一个。

简单的记为四私一公

(1).私有的静态属性(private static $instance),用来储存生成的对象

(2).私有的构造函数(private function __construct())

(3).私有的克隆函数(private function __clone()),防止外部克隆对象

(4).私有的反序列化函数(private function __wakeup()),防止实例被序列化

(5).公共的静态方法(public static function getInstance()),用来访问静态属性储存的对象,如果没有对象,则生成此单例

(6).关键字 instanceof,检查次变量是否为该类的对象,子类,或者是实现接口。

为什么要使用单例模式

php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的 new 操作消耗的资源。

如果一个系统中需要有一个类来全局控制某些配置信息,那么使用单例模式会很方便的实现

在一次页面请求中,为了便于进行调试,因为所有的代码(例如数据库操作类DB)都集中在一个类中,我们可以在类中设置钩子,输出日志,从而避免到处 var_dump echo。

单例模式解决的问题

单例模式解决的是如何在整个项目中创建唯一的对象实例的问题,单例模式和工厂模式可以产生更加合理的对象。

多例模式使用场景

2 个数据库连接器,比如一个是 MySQL ,另一个是 SQLite

多个记录器(一个用于记录调试消息,一个用于记录错误)

示例

单例模式

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
<?php

/**
* 创建一个单例类
* Class single
*/
final class Singleton
{
/**
* @var Object 保存类实例的静态成员变量
*/
static private $instance;

/**
* Single constructor. 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
private function __construct(){}

/**
* @return Object|Single 通过懒加载获得实例(在第一次使用的时候创建)
*/
public static function getInstance() : Singleton
{
if (null === static::$instance) {
static::$instance = new static();
}
return self::$instance;
}

/**
* @purpose: 防止实例被克隆(这会创建实例的副本)
*/
private function __clone(){}

/**
* @purpose: 防止反序列化(这将创建它的副本)
*/
private function __wakeup(){}

}

多例模式

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
<?php

final class Multiton
{
const INSTANCE_1 = '1';
const INSTANCE_2 = '2';

/**
* @var array 实例数组
*/
private static $instances = [];

/**
* 这里私有方法阻止用户随意的创建该对象实例
*/
private function __construct(){}

public static function getInstance(string $instanceName): Multiton
{
if (!isset(self::$instances[$instanceName])) {
self::$instances[$instanceName] = new self();
}

return self::$instances[$instanceName];
}

/**
* 该私有对象阻止实例被克隆
*/
private function __clone(){}

/**
* 该私有方法阻止实例被序列化
*/
private function __wakeup(){}
}
Buy me a cup of milkshake 🍨.
------------- 💖 🌞 本 文 结 束 😚 感 谢 您 的 阅 读 🌞 💖 -------------

欢迎关注我的其它发布渠道