php设计模式之单例模式

来源:互联网 发布:apache与nginx的区别 编辑:程序博客网 时间:2024/05/16 11:03
/*
单例类:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。
1、构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;
2、拥有一个保存类的实例的静态成员变量
3、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)
另外,需要创建__clone()方法防止对象被复制(克隆)
为什么要使用PHP单例模式?
1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。
2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 
3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。

*/

class danli{//保存类实例的静态成员变量private static $instance;//private标记的构造方法private function __construct(){echo 'this is a constructed method'.'<br/>';}//创建__clone方法防止对象被复制克隆,//public function __clone(){//trigger_error('clone is not allowed',E_USER_ERROR);//}//也可以将__clone方法设为private,覆盖__clone,禁止克隆private function __clone(){}//单例方法,用于访闻实例的公共的静态方法public static function getInstance(){if(!(self::$instance instanceof self)){self::$instance=new self;}return self::$instance;}public function test(){echo '调用成功';}}header('content-type:text/html;charset=utf-8');//用new 实例化private标记构造函数的类会报错//$danli=new danli();//Fatal error: Call to private danli::__construct() //正确用法$danli1=danli::getInstance();//$danli1->test();//当再创建对象时,其实是和第一个对象完全一样$danli2=danli::getInstance();if($danli1===$danli2){echo '两个对象完全一样'.'<br/>';}else{echo '两个对象不一样';}//复制,克隆对象将导致一个E_USER_ERROR$danli3=clone($danli1);//Fatal error: Call to private danli::__clone()?>

下面是我找到的一份关于php单例模式解析和实战的文章:

为什么要使用单例模式?

1、PHP缺点:        

        PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。

2、单例模式在PHP中的应用场合:

(1)、应用程序与数据库交互

        一个应用中会存在大量的数据库操作,比如过数据库句柄来连接数据库这一行为,使用单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源。

(2)、控制配置信息

        如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现.

如何实现单例模式?(应用单例模式对数据库进行操作:

<?php/*单例模式:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。单例模式三要点:1,需要一个保存类的唯一实例的静态成员变量:private static $_instance;  2,构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义:private function __construct()   {       $this->_db = pg_connect('xxxx');  }   private function __clone()  {  }//覆盖__clone()方法,禁止克隆  3,必须提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一实例的一个引用 public static function getInstance()    {        if(! (self::$_instance instanceof self) )       {            self::$_instance = new self();        }      return self::$_instance;      }   */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'=>'最近你啦','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>";?>



0 0
原创粉丝点击