[转]单例模式与静态变量在PHP中
在PHP中,没有普遍意义上的静态变量。与Java、C++不同,PHP中的静态变量的存活周期仅仅是每次PHP的会话周期,所以注定了不会有Java或者C++那种静态变量。
所以,在PHP中,静态变量的存在意义仅仅是在某个结构体中(方法或者类)中传递一个变量,其作用域在此文件内。
看个例子好了
1
2
3
4
5
6
7
8
9
10
11
function test(){
static $var = 1;
echo $var++.'<br />';
}
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++.'<br />';
echo $this->b++.'<br />';
}
}
$class1 = new A();
$class1->add();
$class1->add();
$class2 = new A();
$class2->add();
$class2->add();
//Output
//1
//2
//2
//3
//3
//2
//4
//3
从上面的类的运行结果来看,也得到了在函数中相同的结果
那么大概总结一下就是
PHP的静态变量在所在对应的结构体的生命周期中永久存在,并且值保持一致,不论这个结构体被调用或者实例化了多少次。
其实这就是动态变量和静态变量的区别,具体看此篇文章。动态变量只在类中有效,而静态变量在当前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 '<br />';
$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
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 '<br />';
$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单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的
[转]单例模式与静态变量在PHP中的更多相关文章
- 单例模式与静态变量在PHP中
在PHP中,没有普遍意义上的静态变量.与Java.C++不同,PHP中的静态变量的存活周期仅仅是每次PHP的会话周期,所以注定了不会有Java或者C++那种静态变量. 1. 静态变量在PHP中 在PH ...
- 单例模式与静态变量在PHP中 (转载)
在PHP中,没有普遍意义上的静态变量.与Java.C++不同,PHP中的静态变量的存活周期仅仅是每次PHP的会话周期,所以注定了不会有Java或者C++那种静态变量. 所以,在PHP中,静态变量的存在 ...
- 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例
内部类访问外部类的变量必须是final吗? 如下: package com.java.concurrent; class A { int i = 3; public void shout() { cl ...
- 解析Java中静态变量与实例变量的区别
java类的成员变量有俩种:一种是被static关键字修饰的变量,叫类变量或者静态变量:另一种没有static修饰,为实例变量. 在语法定义上的区别:静态变量前要加static关键字,而实例 ...
- java中的成员变量、静态变量与局部变量
java中的变量分为成员变量(又叫实例变量).静态变量和局部变量. 1.成员变量 1.1 成员变量(实例变量)是在类中定义的非static修饰的变量,可以不用赋初始值,不同的数据类型有默认的初始值. ...
- Qt中静态变量使用方法
静态变量可以在各个页面之前使用 先定义一个用于存放静态变量的类 例如datavar 在datavar.h中添加如下代码 #ifndef DATAVAR_H #define DATAVAR_H #inc ...
- Java中的静态变量static
package com.wangcf; public class Test { String name="你好"; static String sex="男"; ...
- matlab中的静态变量与全局变量
matlab中的静态变量和全局变量 1.静态变量 在matlab中,和其他语言一样,函数中的变量一把都是局部变量,也就是说,在函数调用完毕后,变量就会被释放.但是有些时候回希望上次改变的变量在下一次调 ...
- Java中静态变量与非静态变量的区别
感谢大佬:https://www.cnblogs.com/liuhuijie/p/9175167.html ①java类的成员变量有俩种: 一种是被static关键字修饰的变量,叫类变量或者静态变量 ...
随机推荐
- lambda -- Filter Java Stream to 1 and only 1 element
up vote10down votefavorite I am trying to use Java 8 Streams to find elements in a LinkedList. I wan ...
- solr异常--Expected mime type application/octet-stream but got text/html.
Exception in thread "main" org.apache.solr.client.solrj.impl.HttpSolrServer$RemoteSolrExce ...
- 可压Navier-Stokes方程组的爆破现象
在 Z.P. Xin, Blowup of smooth solutions to the compressible Navier-Stokes equations with compact den ...
- Delphi WebService 需要注意 转
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gang4415.blog.51cto.com/225775/251997 Web ...
- 网络编程——TCP协议的三次握手和四次挥手
三次握手原理解析 TCP握手协议在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND ...
- UIImageVIew的使用
UIImageView是一个用于显示图片的控件 构造方法: UIImage * tempImage = [UIImage imageNamed:IMAGE_NAME]; imageVi ...
- 把mysql 中的字符gb2312 改为gbk的方法
第一步:查找mysql的字符: mysql> show variables like '%char%';+--------------------------+----------------- ...
- 《算法问题实战策略》——chaper9——动态规划法技巧
Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1) 拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2) 棋盘中还剩 ...
- Google翻译
本博文的主要内容有 .Google翻译的介绍 .Google翻译之一:内容板块的翻译 .Google翻译之二:网页的翻译 .Google翻译之四:文档的翻译 .Google翻译之四 ...
- Corn Fields - POJ 3254(状态压缩)
题目大意:有一个M*N的牧场,G(i, j) = 1表示这块地营养丰富,可以喂养牛,等于0表示贫瘠,不能喂养牛,所有的牛都讨厌与别的牛相邻,求有多少种放置牛的方式. 分析:算是炮兵那个题的弱化版吧,先 ...