PHP单例模式应用示例【多次连接数据库只实例化一次】

本文实例讲述了PHP单例模式应用。分享给大家供大家参考,具体如下:

以前刚开始工作的时候经常连接数据库,每次用到数据库的时候就要用new进行实例并连接一次,当时因为连接数据库的次数不是很频繁,所以也没什么。后来主管对我说我现在这样每次都连接数据库的如果数据读取频繁的话对数据库和系统造成的压力会很大,让我想想办法能不能就连接一次数据库然后再次用到的时候就不用new一个新的连接了,当时怎么也没想到好的办法,知道最近学到了单例模式才恍然大悟,当时主管是引导我用单例模式的,只怪我以前对开发模式不懂。好了废话少说,下面来看单例模式:

单例模式(职责模式):

简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任务;

单例类:

1、构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;

2、拥有一个保存类的实例的静态成员变量

3、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)

另外,需要创建__clone()方法防止对象被复制(克隆)

为什么要使用PHP单例模式?

1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。

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

3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo

代码(官方文档中的):

<?php
class Singletons{
  // 保存类实例在此属性中
  private static $instance;
  // 构造方法声明为private,防止直接创建对象
  private function __construct()
  {
    echo 'Iam constructed';
  }
  // singleton 方法
  public static function singleton()
  {
    if (!isset(self::$instance)) {
      $c = __CLASS__;
      self::$instance =new$c;
    }
    return self::$instance;
  }
  // Example类中的普通方法
  public function bark()
  {
    echo 'Woof!';
  }
  // 阻止用户复制对象实例
  public function __clone()
  {
    trigger_error('Clone is not allowed.',E_USER_ERROR);
  }
}//endclass singletons
  //这个写法会出错,因为构造方法被声明为private
  //$test= new Singletons();
  // 下面将得到Example类的单例对象
  $test= Singletons::singleton();
  $test->bark();
  // 复制对象将导致一个E_USER_ERROR.
  $test_clone= clone $test;
?>

结果:

I am constructed!   Woof!
Fatal error:
Clone is not allowed. in E:\APMServ5.2.6\www\htdocs\Lee\myprogram\other\class\singletons.phpon line 31

以下内容源自网络(可以参考学习一下):

单例模式的三个要点:

(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;
}

二、为什么要使用单例模式?

1、PHP缺点:

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

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

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

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

(2)、控制配置信息

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

三、如何实现单例模式?

1、普通的数据库访问例子:

<?php
 ......
 //初始化一个数据库句柄
 $db = new DB(...);
 //添加用户信息
 $db->addUserInfo(...);
 ......
//在函数中访问数据库,查找用户信息
function getUserInfo()
{
  $db = new DB(...);//再次new 数据库类,和数据库建立连接
  $db = query(....);//根据查询语句访问数据库
}
?>

2、应用单例模式对数据库进行操作:

<?php
 class DB
 {
   private $_db;
   private static $_instance;
   private function __construct(...)
   {
    $this->_db = pg_connect(...);//postgrsql
  }
  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(...);
?>

3、深入理解

<?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'=>'最近你啦','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>";
?>

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

(0)

相关推荐

  • php设计模式 Bridge (桥接模式)

    复制代码 代码如下: <?php /** * 桥接模式 * * 将抽象部份与它实现部分分离,使用它们都可以有独立的变化 */ abstract class Implementor { abstract public function operation(); } class ConcreteImplementorA extends Implementor { public function operation() { echo "ConcreteImplementorA Operation

  • php观察者模式应用场景实例详解

    本文实例讲述了php观察者模式的应用.分享给大家供大家参考,具体如下: <?php /** * 观察者模式应用场景实例 * * 免责声明:本文只是以哈票网举例,示例中并未涉及哈票网任何业务代码,全部原创,如有雷同,纯属巧合. * * 场景描述: * 哈票以购票为核心业务(此模式不限于该业务),但围绕购票会产生不同的其他逻辑,如: * 1.购票后记录文本日志 * 2.购票后记录数据库日志 * 3.购票后发送短信 * 4.购票送抵扣卷.兑换卷.积分 * 5.其他各类活动等 * * 传统解决方案: *

  • php设计模式之命令模式的应用详解

    命令模式:将一个请求封装为一个对象,从而你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销操作. 命令类:1.命令角色:声明了一个给所有具体命令类的抽象接口.这是一个抽象角色.2.具体命令角色:定义一个接受者和行为之间的弱耦合:实现execute方法,负责调用接受的相应操作.execute()方法通常叫做执行方法3.客户角色:创建一个具体命令对象并确定其接受者.4.请求者角色:负责调用命令对象执行请求,相关的方法叫做行动方法.5.接受者角色:负责具体实施和执行一个请求.作

  • php 策略模式原理与应用深入理解

    本文实例讲述了php 策略模式原理与应用.分享给大家供大家参考,具体如下: 策略模式 简单理解就是 有n个做法供你选择,根据你的需要选择某个策略得到结果 就应用场景来说: 例1:比如购买商品需要支付,你可以提供 微信支付.支付宝支付.支付通支付....(不同的支付方式就是不同的策略) 例2:购物车对产品的计价,如非vip 按原价计算 .vip按8折计算.有推广积分的可以用100积分抵20块...(不同的客户条件计价算法有所不同,只是这里的策略选择是根据登录顾客资料来变动的,当然也可以用观察者模式

  • PHP 观察者模式深入理解与应用分析

    本文实例讲述了PHP 观察者模式.分享给大家供大家参考,具体如下: 用模式开发的优点是,能让我们的逻辑结构以及代码更加清晰,便于维护! 而我们为什么要用 "观察者模式"?这就需要从实际运用中来理解才能更好的运用!用如下的情境来说明吧. 事例,开始时我被安排做项目的登录,很快我就完成了.然后产品提出了另一个需求,用户登录后,给他们推送一条实时消息!然后我在登录成功的逻辑后加了一段代码,完成了登录后的实时消息推送.然而事情还没有完,产品又给加了个需求,需要给新登录的用户10块钱红包奖励,这

  • php桥接模式应用案例分析

    本文实例讲述了php桥接模式应用.分享给大家供大家参考,具体如下: 桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例: 当一个信息时 根据发送渠道分为:QQ消息.email消息.短信消息等 根据消息类型分为:普通.警告.危急等 每种消息都有三种类型(普通QQ消息.警告QQ消息.危急QQ消息...), 每种情况单独写一个类就需要写九个,如果扩展一个类型,就需要再写三个类. 使用桥接模式,可以减少类的数量,易扩展 abstract class info{ public $msg

  • php设计模式之单例、多例设计模式的应用分析

    单例(Singleton)模式和不常见的多例(Multiton)模式控制着应用程序中类的数量.如模式名称,单例只能实例化一次,只有一个对象,多例模式可以多次实例化. 基于Singleton的特性,我们经常用Singleton配置应用程序并定义应用程序中可能随时访问的变量.但有时并不推荐使用Singleton,因为它生成了一个全局状态且 该单一根对象没有封装任何系统功能.多数情况下,会使单元测试和调试变得困难.读者根据情况自行决定.代码示例: 复制代码 代码如下: <?phpclass Singl

  • 基于php设计模式中单例模式的应用分析

    单例模式:简单的说,一个对象只负责一个特定的任务. 单例类:    1.构造函数需要标记为private,单例类不能再其他类中实例化,只能被其自身实例化    2.拥有一个保存类的实例静态成员变量    3.拥有一个访问这个实例的公共的静态方法.[常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到此类是否已经被实例化]    注:需要创建__clone()方法防治对象被复制作用:    1.php的应用主要用于数据库,所以一个应用中会存在大量的数据库操作

  • 鸡肋的PHP单例模式应用详解

    单例模式的要点有三个:一是某个类只能有一个实例:二是它必须自行创建这个实例:三是它必须自行向整个系统提供这个实例. 复制代码 代码如下: <?php /* 单例模式举例,其要点如下: * * 1. $_instance 必须声明为静态的私有变量 * 2. 构造函数和克隆函数必须声明为私有的,这是为了防止外部程序 new 类从而失去单例模式的意义 * 3. getInstance()方法必须声明为公有的,必须调用此方法以返回唯一实例的一个引用 * 4. ::操作符只能访问静态变量或静态函数 * 5

  • PHP CLI模式下的多进程应用分析

    PHP在很多时候不适合做常驻的SHELL进程, 他没有专门的gc例程, 也没有有效的内存管理途径. 所以如果用PHP做常驻SHELL, 你会经常被内存耗尽导致abort而unhappy. 而且, 如果输入数据非法, 而脚本没有检测, 导致abort, 也会让你很不开心. 那? 怎么办呢? 多进程-. 为什么呢? 优点: 1. 使用多进程, 子进程结束以后, 内核会负责回收资源 2. 使用多进程,子进程异常退出不会导致整个进程Thread退出. 父进程还有机会重建流程. 3. 一个常驻主进程, 只

随机推荐