PHP设计模式之单例模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP设计模式之单例模式相关的知识,希望对你有一定的参考价值。
参考:http://www.cnblogs.com/yangjinjin/archive/2013/01/31/2887492.html
李炎恢php第三季视频
单例模式
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式有以下3个特点:
1.只能有一个实例。
2.必须自行创建这个实例。
3.必须给其他对象提供这一实例。
PHP一个主要应用场合就是应用程序与数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库句柄连接数据库的行为,使用单例模式可以避免大量的new操作。因为每一次new操作都会消耗系统和内存的资源。
//初始化一个数据库句柄$db = new DB(...);//比如有个应用场景是添加一条用户信息
$db->addUserInfo();....../
/然而我们要在另一地方使用这个用户信息,这时要用到数据库句柄资源,可能会这么做
......function test() {
$db = new DB(...);
$db->getUserInfo();......
有些朋友也许会说,可以直接使用global关键字!
global $db;
的确global可以解决问题,也起到单例模式的作用,但在OOP中,我们拒绝这种编码。因为global存在安全隐患(全局变量不受保护的本质)。
全局变量是面向对象程序员遇到的引发BUG的主要原因之一。这是因为全局变量将类捆绑于特定的环境,破坏了封装。如果新的应用程序无法保证一开始就定义了相同的全局变量,那么一个依赖于全局变量的类就无法从一个应用程序中提取出来并应用到新应用程序中。
确切的讲,单例模式恰恰是对全局变量的一种改进,避免那些存储唯一实例的全局变量污染命名空间。你无法用错误类型的数据覆写一个单例。这种保护在不支持命名空间的PHP版本里尤其重要。因为在PHP中命名冲突会在编译时被捕获,并使脚本停止运行。
以实例化数据库连接为例:
<?php
class DB{
private $_db;
//静态可以通过类直接访问,不需要new,private外部不能访问
static private $_instance;
//访问这个实例的公共静态方法
static public function getInstance()
{
//如果对象没有创建就创建并返回,如果已经创建过就直接返回
if (!(self::$_instance instanceof self)){
self::$_instance = new self();
}
return self::$_instance;
}
//单一职责问题,私有化clone
private function __clone(){}
private function __construct()
{
try{
$this->_db = new PDO(‘mysql:host=127.0.0.1;dbname=shop3‘,‘root‘,‘‘);
echo ‘创建了一次数据库连接对象‘.‘<br/>‘;
}catch (PDOException $e){
exit($e->getMessage());
}
}
public function query($sql)
{
return $this->_db->query($sql);
}
}
首先是实例化对象的时候,调用构造方法,实例化一个PDO对象,建立起数据库连接,将句柄赋值给私有属性$_db。但是构造方法是私有属性,也就是说只能在类内调用.所以直接new DB()的话会报错,无法调用DB类内的私有属性。往上看有一个静态方法getInstance(),静态方法是可以通过类名直接调用并且是不需要实例化对象的。比如DB::getInstance()就可以在类外调用这个方法了。
看getInstance()方法:
先判断当前类是否被创建过,如果没有就实例化并且赋值给静态属性$_instance,否则就直接返回$_instance,self::$_instance表示实例化过后DB类的句柄。也就是说不管调用多少次getInstance方法,最终也只会实例化一次DB类对象。
DB类单一职责就要求不能被clone,所以也私有化__clone方法
结论:单例模式可以很好的替代全局变量。虽然单例模式也存在和全局变量一样的缺点 ,
比如依赖性,因此我们应当小心谨慎的使用单例模式
以上是关于PHP设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章