PHP單例模式是什么 php實現(xiàn)單例模式的方法

字號:


    PHP單例模式是什么?這篇文章主要介紹了php實現(xiàn)單例模式的方法,告訴大家為什么使用單例模式,感興趣的朋友可以參考一下
    一、什么是單例模式?
    1、含義   
    作為對象的創(chuàng)建模式,單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)全局地提供這個實例。它不會創(chuàng)建實例副本,而是會向單例類內部存儲的實例返回一個引用。
    2、單例模式的三個要點:
    (1). 需要一個保存類的唯一實例的靜態(tài)成員變量:
    private static $_instance;   
    (2). 構造函數(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í)行后,所有的相關資源都會被回收。也就是說,PHP在語言級別上沒有辦法讓某個對象常駐內存,這和asp.net、Java等編譯型是不同的,比如在Java中單例會一直存在于整個應用程序的生命周期里,變量是跨頁面級的,真正可以做到這個實例在應用程序生命周期中的唯一性。然而在PHP中,所有的變量無論是全局變量還是類的靜態(tài)成員,都是頁面級的,每次頁面被執(zhí)行時,都會重新建立新的對象,都會在頁面執(zhí)行完畢后被清空,這樣似乎PHP單例模式就沒有什么意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現(xiàn)多個應用場景并需要共享同一對象資源時是非常有意義的。
    2、單例模式在PHP中的應用場合:
    (1)、應用程序與數(shù)據(jù)庫交互
    一個應用中會存在大量的數(shù)據(jù)庫操作,比如過數(shù)據(jù)庫句柄來連接數(shù)據(jù)庫這一行為,使用單例模式可以避免大量的new操作,因為每一次new操作都會消耗內存資源和系統(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、應用單例模式對數(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;
      /**
       * 構造
       * 
       * @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 事務開始
       */
      private function beginTransaction()
      {
        $this->dbh->beginTransaction();
      }
      /**
       * commit 事務提交
       */
      private function commit()
      {
        $this->dbh->commit();
      }
      /**
       * rollback 事務回滾
       */
      private function rollback()
      {
        $this->dbh->rollback();
      }
      /**
       * transaction 通過事務處理多條SQL語句
       * 調用前需通過getTableEngine判斷表引擎是否支持事務
       *
       * @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 關閉數(shù)據(jù)庫連接
       */
      public function destruct()
      {
        $this->dbh = null;
      }
    }
    ?>
    調用方法:
    <?php
    require 'MyPDO.class.php';
    $db = MyPDO::getInstance('localhost', 'root', '123456', 'test', 'utf8');
    $db->query("select count(*) frome table");
    $db->destruct();
    ?>
    以上就是本文的全部內容,希望對大家學習php程序設計有所幫助。