单例模式与静态变量在 PHP 中 | BNDong
0%

单例模式与静态变量在 PHP 中

在PHP中,没有普遍意义上的静态变量。与Java、C++不同,PHP中的静态变量的存活周期仅仅是每次PHP的会话周期,所以注定了不会有Java或者C++那种静态变量。

静态变量在PHP中

在PHP中,静态变量的存在意义仅仅是在某个结构体中(方法或者类)中传递一个变量,其作用域在此文件内。

1
2
3
4
5
6
7
8
9
10
11
function test(){
static $var = 1;
echo $var++.'';
}
test();
test();
test();
//OutPut
//1
//2
//3

test 函数的三次调用中,变量 $var 在三次调用中都是存在的,并且每次会递增1,而并没有清空或者重置
所以可以得出一个结论,静态变量在当前结构体所在的生命周期中一直存在。当前的例子中, test 函数的生命周期就是当前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
class A
{
private static $a = 1;
private $b = 2;
public function add()
{
echo self::$a++.'';
echo $this->b++.'';
}
}
$class1 = new A();
$class1->add();
$class1->add();
$class2 = new A();
$class2->add();
$class2->add();
//Output
//1
//2
//2
//3
//3
//2
//4
//3

从上面的类的运行结果来看,也得到了在函数中相同的结果
那么大概总结一下就是
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
class A
{
private static $instance = null;
private $b = 1;
public static function get_instance()
{
if(self::$instance == null){
$classname = __CLASS__;
self::$instance = new $classname();
}
return self::$instance;
}
public function add()
{
$this->b++;
}
public function show()
{
echo $this->b;
}
}
$a = A::get_instance();
$b = A::get_instance();
//此处$a和$b变量完全相同!
$a->add();
$a->show();
echo '';
$b->show();
//output
//2
//2

此时,由于单例模式存在,使得 $a$b 完全是同一个对象,所以之间如果需要共享数据,完全不需要静态变量(废话,就是自己。因为在任何时候,应用程序中都只会有这个类仅有的一个实例存在!无论你调用多少次单例,里面的数据是不会被重新实例化的。)

所以,在单例模式中,静态变量根本就没有存在的意义。当然,如果你没事干,非要使用new方法来初始化对象的话,也行,此时单例模式被打破,回归到无单例模式的状态。

如果为了防止使用new来实例化对象,那么可以考虑对类的 __construct 函数设置为 private 属性

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
class A
{
private static $instance = null;
private $b = 1;
private function __construct()
{
//Code in this function
//could not be get out of the class
}
public static function get_instance()
{
if(self::$instance == null){
$classname = __CLASS__;
self::$instance = new $classname();
}
return self::$instance;
}
public function add()
{
$this->b++;
}
public function show()
{
echo $this->b;
}
}
$a = A::get_instance();
$b = A::get_instance();
//此处$a和$b 变量完全相同!
$a->add();
$a->show();
echo '
';
$b->show();
//output
//2
//2

//如果尝试用new来实例化的话
$c = new A();
//output
//Fatal error: Call to private A::__construct() from invalid context in
//如果需要A类的实例化对象,只能通过开放的get_instance静态方法进行初始化

优点:单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源

缺点:在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的

↓赏一个鸡腿... 要不,半个也行↓