PHP中的对象生存期间是从该脚本开始一直到该脚本结束为止,因此PHP的单例模式只是在一个页面中(这里可能包含很多其他页面,不是狭义的单页面)多次用到该对象时才会起作用,多次用到时不去重复的new对象(多个人做一个项目时,难免会碰到一次请求中多次实例一个对象的情况),将不会耗费不必要的资源(数据控连接操做效果很明显),还有一点就是可以保证整个脚本中都是同一个对象,这种模式是怎么实现的呢,他的实现有几个要注意的点:
1. 首先就是要将__construct()方法定义为私有方法,这样就不能通过new来得到一个新的实例了,单例模式不能在外部进行实例化,这能字自身内部进行实例化;
2. 同样要屏蔽__clone()方法,防止从类外部进行克隆
3. 然后就是定义一个用来保存实例的私有变量和获取私有变量的公有函数getInstance()
<?php /** * 设计模式之单例模式 * $_instance必须声明为静态的私有变量 * 构造函数必须声明为私有,防止外部程序new类从而失去单例模式的意义 * getInstance()方法必须设置为公有的,必须调用此方法以返回实例的一个引用 * ::操作符只能访问静态变量和静态函数 * new对象都会消耗内存 * 使用场景:最常用的地方是数据库连接。 * class Singlemodel{ /** * 保存Singlemodel实例的变量 * @var Singlemodel $_instance */ private static $_instance = null; /** * 屏蔽掉通过new来实例化该对象(也可以去掉) * 这里来测试数据库连接 */ private function __construct(){ header("Content-Type:text/html;charset=utf-8"); } /** * 通过该方法获取实例,防止多次实例化 */ public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self(); } return self::$_instance; } /** * 测试1,通过使用单例模式 */ public static function testOne(){ return self::getInstance(); } /** * 测试1,通过使用单例模式 */ public static function testTwo(){ return new self(); } } $obj = array(); $begin = microtime(true); for($i=0;$i<10000;$i++){ /* * 这里进行两次测试,testOne应用了单例模式,testTwo没有应用单例模式, * 我们分别看看他们占用的资源和耗费的时间 */ $obj[$i] = Singlemodel::testOne(); // $obj[$i] = Singlemodel::testTwo(); } echo "程序运行期间最大内存占用:".memory_get_peak_usage()."bytes\r"; echo "程序运行耗时:".floatval(microtime(true) - $begin)."s\r";
5次测试结果平均:
未使用单例模式: 程序运行期间最大内存占用:2341720bytes 程序运行耗时:0.0505061149597s 使用单例模式: 程序运行期间最大内存占用: 613272bytes 程序运行耗时:0.018285036087s
到这里,你要是自己测试过就会发现,当链接次数比较少时,差异是比较小的。其实在一次请求中达到很多次实例化也是比较少的,那么是不是说这个就没作用了呢,当然不是,你想想看,首先,这样可以尽量避免多次实例化,减小资源消耗;其次,就算是这10ms级的差距,在高并发系统中也是很有用的。我们用它好处多多