Singleton Pattern----单例模式
一. 概念
一个类有且只能有一个实例,并且自行实例化向整个系统提供这个实例。
二. 使用场景
- 一个应用中会存在大量的数据库操作,每次打开和关闭数据库连接都会消耗一些资源,都需要重新实例化(new)数据库类,每一次new操作都会消耗内存资源和系统资源,而使用单例模式可以避免大量的new操作,减少数据库的连接。
- 一个系统中可能需要一个类来全局控制一些配置信息,那么可以用单例模式来实现。
三. 实现方式
- 私有化一个属性用于存放唯一的一个实例
- 私有化构造方法,私有化克隆方法,用来创建并只允许创建一个实例
- 公有化静态方法,用于向系统提供这个实例
四. 代码实现
class Singleton{ //存放实例,保存类的唯一实例的静态成员变量 private static $_instance = null; //私有化构造方法,防止外部程序new类 private function __construct(){ echo "单例模式的实例被构造了"; } //私有化克隆方法,覆盖__clone()方法,禁止克隆 private function __clone(){ } //公有化获取实例方法,从而返回唯一实例的一个引用 public static function getInstance(){ if (!(self::$_instance instanceof Singleton)){ self::$_instance = new Singleton(); } return self::$_instance; } } //调用方式 $singleton=Singleton::getInstance();
//注:因为静态方法可以在全局范围内被访问,当我们需要一个单例模式的对象时,只需调用getInstance方法,获取先前实例化的对象,无需重新实例化。
注意:
- PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我认为只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时,才是非常有意义的。
五.Trait实现继承单例类
Trait Singleton{ //存放实例 private static $_instance = null; //私有化克隆方法 private function __clone(){ } //公有化获取实例方法 public static function getInstance(){ $class = __CLASS__; if (!(self::$_instance instanceof $class)){ self::$_instance = new $class(); } return self::$_instance; } } class DB { private function __construct(){ echo __CLASS__.PHP_EOL; } } class DBhandle extends DB { use Singleton; private function __construct(){ echo "单例模式的实例被构造了"; } } //调用方式 $handle=DBhandle::getInstance(); //注:若父类方法为public,则子类只能为pubic,若父类为private,子类为public ,protected,private都可以。
六. 数据库使用单例
- 普通的数据库访问例子:
<?php ...... //初始化一个数据库句柄 $db = new DB(...); //添加用户信息 $db->addUserInfo(...);
...... //在函数中访问数据库,查找用户信息 function getUserInfo(){ $db = new DB(...);//再次new 数据库类,和数据库建立连接 $db = query(....);//根据查询语句访问数据库 } ?>
- 应用单例模式对数据库进行操作:
<?php class DB{ private $_db; private static $_instance; private function __construct(...){ $this->_db = pg_connect(...); } private function __clone() {}; //覆盖__clone()方法,禁止克隆 public static function getInstance(){ if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function addUserInfo(...){ } public function getUserInfo(...){ } } //test $db = DB::getInstance(); $db->addUserInfo(...); $db->getUserInfo(...); ?>
- 简单数据库单例类
<?php class db { public $conn; public static $sql; public static $instance=null; private function __construct(){ require_once('db.config.php'); $this->conn = mysql_connect($db['host'],$db['user'],$db['password']); if(!mysql_select_db($db['database'],$this->conn)){ echo "失败"; }; mysql_query('set names utf8',$this->conn); } public static function getInstance(){ if(is_null(self::$instance)){ self::$instance = new db; } return self::$instance; } /** * 查询数据库 */ public function select($table,$condition=array(),$field = array()){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } $fieldstr = ''; if(!empty($field)){ foreach($field as $k=>$v){ $fieldstr.= $v.','; } $fieldstr = rtrim($fieldstr,','); }else{ $fieldstr = '*'; } self::$sql = "select {$fieldstr} from {$table} {$where}"; $result=mysql_query(self::$sql,$this->conn); $resuleRow = array(); $i = 0; while($row=mysql_fetch_assoc($result)){ foreach($row as $k=>$v){ $resuleRow[$i][$k] = $v; } $i++; } return $resuleRow; } /** * 添加一条记录 */ public function insert($table,$data){ $values = ''; $datas = ''; foreach($data as $k=>$v){ $values.=$k.','; $datas.="'$v'".','; } $values = rtrim($values,','); $datas = rtrim($datas,','); self::$sql = "INSERT INTO {$table} ({$values}) VALUES ({$datas})"; if(mysql_query(self::$sql)){ return mysql_insert_id(); }else{ return false; }; } /** * 修改一条记录 */ public function update($table,$data,$condition=array()){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } $updatastr = ''; if(!empty($data)){ foreach($data as $k=>$v){ $updatastr.= $k."='".$v."',"; } $updatastr = 'set '.rtrim($updatastr,','); } self::$sql = "update {$table} {$updatastr} {$where}"; return mysql_query(self::$sql); } /** * 删除记录 */ public function delete($table,$condition){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } self::$sql = "delete from {$table} {$where}"; return mysql_query(self::$sql); } public static function getLastSql(){ echo self::$sql; } } $db = db::getInstance(); //$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password')); //echo $db->insert('demo',array('name'=>'aaa','password'=>'123')); //echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1)); echo $db->delete('demo',array('id'=>'2')); db::getLastSql(); echo "<pre>"; ?>