PHP單例模式是什么 php實現(xiàn)單例模式的方法
來源:易賢網(wǎng) 閱讀:887 次 日期:2016-08-22 15:39:52
溫馨提示:易賢網(wǎng)小編為您整理了“PHP單例模式是什么 php實現(xiàn)單例模式的方法”,方便廣大網(wǎng)友查閱!

PHP單例模式是什么?這篇文章主要介紹了php實現(xiàn)單例模式的方法,告訴大家為什么使用單例模式,感興趣的朋友可以參考一下

一、什么是單例模式?

1、含義   

作為對象的創(chuàng)建模式,單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)全局地提供這個實例。它不會創(chuàng)建實例副本,而是會向單例類內(nèi)部存儲的實例返回一個引用。

2、單例模式的三個要點:

(1). 需要一個保存類的唯一實例的靜態(tài)成員變量:

private static $_instance;   

(2). 構(gòu)造函數(shù)和克隆函數(shù)必須聲明為私有的,防止外部程序new類從而失去單例模式的意義:

private function __construct()  

{  

  $this->_db = pg_connect('xxxx'); 

}  

private function __clone() 

}//覆蓋__clone()方法,禁止克隆 

(3). 必須提供一個訪問這個實例的公共的靜態(tài)方法(通常為getInstance方法),從而返回唯一實例的一個引用 

public static function getInstance()  

{  

  if(! (self::$_instance instanceof self) )  

  {  

    self::$_instance = new self();  

  } 

  return self::$_instance;  

}  

二、為什么要使用單例模式?

1、PHP缺點:

PHP語言是一種解釋型的腳本語言,這種運行機制使得每個PHP頁面被解釋執(zhí)行后,所有的相關(guān)資源都會被回收。也就是說,PHP在語言級別上沒有辦法讓某個對象常駐內(nèi)存,這和asp.net、Java等編譯型是不同的,比如在Java中單例會一直存在于整個應(yīng)用程序的生命周期里,變量是跨頁面級的,真正可以做到這個實例在應(yīng)用程序生命周期中的唯一性。然而在PHP中,所有的變量無論是全局變量還是類的靜態(tài)成員,都是頁面級的,每次頁面被執(zhí)行時,都會重新建立新的對象,都會在頁面執(zhí)行完畢后被清空,這樣似乎PHP單例模式就沒有什么意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現(xiàn)多個應(yīng)用場景并需要共享同一對象資源時是非常有意義的。

2、單例模式在PHP中的應(yīng)用場合:

(1)、應(yīng)用程序與數(shù)據(jù)庫交互

一個應(yīng)用中會存在大量的數(shù)據(jù)庫操作,比如過數(shù)據(jù)庫句柄來連接數(shù)據(jù)庫這一行為,使用單例模式可以避免大量的new操作,因為每一次new操作都會消耗內(nèi)存資源和系統(tǒng)資源。

(2)、控制配置信息

如果系統(tǒng)中需要有一個類來全局控制某些配置信息, 那么使用單例模式可以很方便的實現(xiàn).

三、如何實現(xiàn)單例模式?

1、普通的數(shù)據(jù)庫訪問例子:

<?php 

...... 

//初始化一個數(shù)據(jù)庫句柄 

$db = new DB(...); 

//添加用戶信息 

$db->addUserInfo(...); 

...... 

//在函數(shù)中訪問數(shù)據(jù)庫,查找用戶信息 

function getUserInfo() 

  $db = new DB(...);//再次new 數(shù)據(jù)庫類,和數(shù)據(jù)庫建立連接 

  $db = query(....);//根據(jù)查詢語句訪問數(shù)據(jù)庫 

?>

2、應(yīng)用單例模式對數(shù)據(jù)庫進行操作:

<?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(...);  

?> 

下面的代碼是PDO操作數(shù)據(jù)庫類的一個封裝,采用了單例模式:

<?php

/**

 * MyPDO

 */

class MyPDO

{

  protected static $_instance = null;

  protected $dbName = '';

  protected $dsn;

  protected $dbh;

  /**

   * 構(gòu)造

   * 

   * @return MyPDO

   */

  private function __construct($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset)

  {

    try {

      $this->dsn = 'mysql:host='.$dbHost.';dbname='.$dbName;

      $this->dbh = new PDO($this->dsn, $dbUser, $dbPasswd);

      $this->dbh->exec('SET character_set_connection='.$dbCharset.', character_set_results='.$dbCharset.', character_set_client=binary');

    } catch (PDOException $e) {

      $this->outputError($e->getMessage());

    }

  }

  /**

   * 防止克隆

   * 

   */

  private function __clone() {}

  /**

   * Singleton instance

   * 

   * @return Object

   */

  public static function getInstance($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset)

  {

    if (self::$_instance === null) {

      self::$_instance = new self($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset);

    }

    return self::$_instance;

  }

  /**

   * Query 查詢

   *

   * @param String $strSql SQL語句

   * @param String $queryMode 查詢方式(All or Row)

   * @param Boolean $debug

   * @return Array

   */

  public function query($strSql, $queryMode = 'All', $debug = false)

  {

    if ($debug === true) $this->debug($strSql);

    $recordset = $this->dbh->query($strSql);

    $this->getPDOError();

    if ($recordset) {

      $recordset->setFetchMode(PDO::FETCH_ASSOC);

      if ($queryMode == 'All') {

        $result = $recordset->fetchAll();

      } elseif ($queryMode == 'Row') {

        $result = $recordset->fetch();

      }

    } else {

      $result = null;

    }

    return $result;

  }

  /**

   * Update 更新

   *

   * @param String $table 表名

   * @param Array $arrayDataValue 字段與值

   * @param String $where 條件

   * @param Boolean $debug

   * @return Int

   */

  public function update($table, $arrayDataValue, $where = '', $debug = false)

  {

    $this->checkFields($table, $arrayDataValue);

    if ($where) {

      $strSql = '';

      foreach ($arrayDataValue as $key => $value) {

        $strSql .= ", `$key`='$value'";

      }

      $strSql = substr($strSql, 1);

      $strSql = "UPDATE `$table` SET $strSql WHERE $where";

    } else {

      $strSql = "REPLACE INTO `$table` (`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')";

    }

    if ($debug === true) $this->debug($strSql);

    $result = $this->dbh->exec($strSql);

    $this->getPDOError();

    return $result;

  }

  /**

   * Insert 插入

   *

   * @param String $table 表名

   * @param Array $arrayDataValue 字段與值

   * @param Boolean $debug

   * @return Int

   */

  public function insert($table, $arrayDataValue, $debug = false)

  {

    $this->checkFields($table, $arrayDataValue);

    $strSql = "INSERT INTO `$table` (`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')";

    if ($debug === true) $this->debug($strSql);

    $result = $this->dbh->exec($strSql);

    $this->getPDOError();

    return $result;

  }

  /**

   * Replace 覆蓋方式插入

   *

   * @param String $table 表名

   * @param Array $arrayDataValue 字段與值

   * @param Boolean $debug

   * @return Int

   */

  public function replace($table, $arrayDataValue, $debug = false)

  {

    $this->checkFields($table, $arrayDataValue);

    $strSql = "REPLACE INTO `$table`(`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')";

    if ($debug === true) $this->debug($strSql);

    $result = $this->dbh->exec($strSql);

    $this->getPDOError();

    return $result;

  }

  /**

   * Delete 刪除

   *

   * @param String $table 表名

   * @param String $where 條件

   * @param Boolean $debug

   * @return Int

   */

  public function delete($table, $where = '', $debug = false)

  {

    if ($where == '') {

      $this->outputError("'WHERE' is Null");

    } else {

      $strSql = "DELETE FROM `$table` WHERE $where";

      if ($debug === true) $this->debug($strSql);

      $result = $this->dbh->exec($strSql);

      $this->getPDOError();

      return $result;

    }

  }

  /**

   * execSql 執(zhí)行SQL語句

   *

   * @param String $strSql

   * @param Boolean $debug

   * @return Int

   */

  public function execSql($strSql, $debug = false)

  {

    if ($debug === true) $this->debug($strSql);

    $result = $this->dbh->exec($strSql);

    $this->getPDOError();

    return $result;

  }

  /**

   * 獲取字段最大值

   * 

   * @param string $table 表名

   * @param string $field_name 字段名

   * @param string $where 條件

   */

  public function getMaxValue($table, $field_name, $where = '', $debug = false)

  {

    $strSql = "SELECT MAX(".$field_name.") AS MAX_VALUE FROM $table";

    if ($where != '') $strSql .= " WHERE $where";

    if ($debug === true) $this->debug($strSql);

    $arrTemp = $this->query($strSql, 'Row');

    $maxValue = $arrTemp["MAX_VALUE"];

    if ($maxValue == "" || $maxValue == null) {

      $maxValue = 0;

    }

    return $maxValue;

  }

  /**

   * 獲取指定列的數(shù)量

   * 

   * @param string $table

   * @param string $field_name

   * @param string $where

   * @param bool $debug

   * @return int

   */

  public function getCount($table, $field_name, $where = '', $debug = false)

  {

    $strSql = "SELECT COUNT($field_name) AS NUM FROM $table";

    if ($where != '') $strSql .= " WHERE $where";

    if ($debug === true) $this->debug($strSql);

    $arrTemp = $this->query($strSql, 'Row');

    return $arrTemp['NUM'];

  }

  /**

   * 獲取表引擎

   * 

   * @param String $dbName 庫名

   * @param String $tableName 表名

   * @param Boolean $debug

   * @return String

   */

  public function getTableEngine($dbName, $tableName)

  {

    $strSql = "SHOW TABLE STATUS FROM $dbName WHERE Name='".$tableName."'";

    $arrayTableInfo = $this->query($strSql);

    $this->getPDOError();

    return $arrayTableInfo[0]['Engine'];

  }

  /**

   * beginTransaction 事務(wù)開始

   */

  private function beginTransaction()

  {

    $this->dbh->beginTransaction();

  }

  /**

   * commit 事務(wù)提交

   */

  private function commit()

  {

    $this->dbh->commit();

  }

  /**

   * rollback 事務(wù)回滾

   */

  private function rollback()

  {

    $this->dbh->rollback();

  }

  /**

   * transaction 通過事務(wù)處理多條SQL語句

   * 調(diào)用前需通過getTableEngine判斷表引擎是否支持事務(wù)

   *

   * @param array $arraySql

   * @return Boolean

   */

  public function execTransaction($arraySql)

  {

    $retval = 1;

    $this->beginTransaction();

    foreach ($arraySql as $strSql) {

      if ($this->execSql($strSql) == 0) $retval = 0;

    }

    if ($retval == 0) {

      $this->rollback();

      return false;

    } else {

      $this->commit();

      return true;

    }

  }

  /**

   * checkFields 檢查指定字段是否在指定數(shù)據(jù)表中存在

   *

   * @param String $table

   * @param array $arrayField

   */

  private function checkFields($table, $arrayFields)

  {

    $fields = $this->getFields($table);

    foreach ($arrayFields as $key => $value) {

      if (!in_array($key, $fields)) {

        $this->outputError("Unknown column `$key` in field list.");

      }

    }

  }

  /**

   * getFields 獲取指定數(shù)據(jù)表中的全部字段名

   *

   * @param String $table 表名

   * @return array

   */

  private function getFields($table)

  {

    $fields = array();

    $recordset = $this->dbh->query("SHOW COLUMNS FROM $table");

    $this->getPDOError();

    $recordset->setFetchMode(PDO::FETCH_ASSOC);

    $result = $recordset->fetchAll();

    foreach ($result as $rows) {

      $fields[] = $rows['Field'];

    }

    return $fields;

  }

  /**

   * getPDOError 捕獲PDO錯誤信息

   */

  private function getPDOError()

  {

    if ($this->dbh->errorCode() != '00000') {

      $arrayError = $this->dbh->errorInfo();

      $this->outputError($arrayError[2]);

    }

  }

  /**

   * debug

   * 

   * @param mixed $debuginfo

   */

  private function debug($debuginfo)

  {

    var_dump($debuginfo);

    exit();

  }

  /**

   * 輸出錯誤信息

   * 

   * @param String $strErrMsg

   */

  private function outputError($strErrMsg)

  {

    throw new Exception('MySQL Error: '.$strErrMsg);

  }

  /**

   * destruct 關(guān)閉數(shù)據(jù)庫連接

   */

  public function destruct()

  {

    $this->dbh = null;

  }

}

?>

調(diào)用方法:

<?php

require 'MyPDO.class.php';

$db = MyPDO::getInstance('localhost', 'root', '123456', 'test', 'utf8');

$db->query("select count(*) frome table");

$db->destruct();

?>

以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)php程序設(shè)計有所幫助。

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機網(wǎng)站地址:PHP單例模式是什么 php實現(xiàn)單例模式的方法
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65317125(9:00—18:00) 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)