在码PHP程序的时候,为了之后更好地维护代码和理解代码,用一些合适的设计模式是必不可少的,下面我和你们首先分享下单例模式,有错误或者不恰当的地方,还望PHPer们帮我指出。php
PHP中的对象生存期间是从该脚本开始一直到该脚本结束为止,所以PHP的单例模式只是在一个页面中(这里可能包含不少其余页面,不是狭义的单页面)屡次用到该对象时才会起做用,屡次用到时不去重复的new对象(多我的作一个项目时,不免会碰到一次请求中屡次实例一个对象的状况),将不会耗费没必要要的资源(数据控链接操作效果很明显),还有一点就是能够保证整个脚本中都是同一个对象,这种模式是怎么实现的呢,他的实现有几个要注意的点:mysql
1. 首先就是要将__construct()方法定义为私有方法,这样就不能经过new来获得一个新的实例了,单例模式不能在外部进行实例化,这能字自身内部进行实例化;sql
2. 一样要屏蔽__clone()方法,防止从类外部进行克隆数据库
2. 而后就是定义一个用来保存实例的私有变量和获取私有变量的公有函数getInstance()。设计模式
<?php /** * 设计模式——单例模式 * @author 燕睿涛(luluyrt@163.com) */ class Singlemodel{ /** * 保存Singlemodel实例的变量 * @var Singlemodel $_instance */ private static $_instance = null; /** * 屏蔽掉经过new来实例化该对象 */ private function __construct(){ //空函数就行 } /**
* 屏蔽掉经过clone来克隆该对象
*/
private function __clone(){
//空函数就行
} /** * 经过该方法获取实例,防止屡次实例化 */ public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self(); } return self::$_instance; } }
空口无凭,光说这些理论的没有说服力,下面经过例子来看下具体的效果差别并发
<?php /** * 设计模式——单例模式——测试 * @author 燕睿涛(luluyrt@163.com) */ class Singlemodel{ /** * 保存Singlemodel实例的变量 * @var Singlemodel $_instance */ private static $_instance = null; private $_link = null; /** * 屏蔽掉经过new来实例化该对象(也能够去掉) * 这里来测试数据库链接 */ private function __construct(){ $this->_link = mysqli_connect("localhost","root","","mysql"); } /** * 经过该方法获取实例,防止屡次实例化 */ 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<100;$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";
先注释$obj[$i] = Singlemodel::testTwo();这一行,使用单例模式,咱们能够获得下面的结果函数
而后注释掉$obj[$i] = Singlemodel::testOne();,使用非单例模式,咱们获得下面结果高并发
能够看到性能
100次测试 | 单例模式 | 普通模式 | 普通/单例(倍) |
内存(bytes) | 143816 | 847376 | 5.89 |
时间(s) | 0.0112519 | 0.2541389 | 22.59 |
5次测试 | |||
bytes | 140432 | 168984 | 1.20 |
s | 0.0112612 | 0.0173110 | 1.54 |
能够看到当一次脚本执行的连接数为100时单例模式的性能比普通模式在内存占用方面好了将近6倍,时间上快了将近23倍,当链接数继续增长的时候倍数会更大,由于单例模式耗费的内存和时间基本没有变化,非单例模式会不停地增大,这里要注意一点就是非单例模式状况下连接数增大到必定程度时会报错"mysqli_connect(): (08004/1040): Trop de connexions in",意思是说并发链接太多了,测试咱们能够经过下面的命令查看mysql最大链接数设置,这点须要注意下,省得不知道为何报错。测试
show variables like 'max_connections';
到这里,你要是本身测试过就会发现,当连接次数比较少时,差别是比较小的(就像上面的一次请求有5次链接时),其实在一次请求中达到不少次实例化也是比较少的,那么是否是说这个就没做用了呢,固然不是,你想一想看,首先,这样能够尽可能避免屡次实例化,减少资源消耗;其次,就算是这10ms级的差距,在高并发系统中也是颇有用的。咱们用它好处多多。
单例模式就这么多了,下次再讲其余设计模式,有什么不对的地方还望留言或者邮件指出,感激涕零!