面向對象中的單例模式(PHP)

單例模式的主要作用是保證在面向對象編程設計中,一個類只能有一個實例對象的存在。在很多操作中,比如建立目錄、數據庫連接都有可能會用到這種技術。和其他面向對象的編程語言相比,PHP中使用單例設計尤爲重要。因爲PHP是腳本語言,每次訪問都是一次獨立執行的過程,而在這個過程中一個類中有一個實例對象就足夠了。例如自定義數據庫的操作類,設計的原則就是在一個腳本中,只需要實例化一個數據庫操作類的對象,並且只連接一次數據庫就可以了,而不是在一個腳本中爲了執行對個SQL語句,單獨爲每個SQL語句實例一個對象,因爲實例化一次就要連接一次數據庫,這樣非常降低效率,單例模式就爲我們提供了這樣實現的可能。另外,使用單例的另一個好處在於可以節省內存,因爲它限制了實例對象的個數。

<?php
/**
 * 聲明一個類Db,用於演示單例模式的使用
 */
class DB{
  //聲明一個私有的,靜態的成員屬性$obj;因爲靜態方法只能訪問
  private static $obj = null;

  /*構造方法,使用private封裝後則只能在類的內部使用new去創建對象*/
  private function __construct(){
    /*在這個方法中完成一些數據庫連接等操作*/
    echo "數據庫連接成功!";
  }

  //只有通過這個方法才能返回本類的對象,該方法是靜態方法,用類名調用
  static function getInstance(){
    if(is_null(self::$obj)){//如果本類中的$obj爲空,說明還沒有被實例化過
      self::$obj = new self();//實例化本類對象
    }
    return self::$obj;
  }

  //執行SQL語句完成數據庫的操作
  function query($sql){
    echo $sql;
  }
}

//只能使用靜態方法getInstance()去獲取DB類的對象
$db = DB::getInstance();

//訪問對象中的成員
$db -> query("select * from user");
 ?>

要編寫單例設計模式,就必須讓一個類只能實例化一個對象,而想讓一個類只實例化一個對象,就先要讓一個類不能實例化對象。在上例中,不能在類的外部直接使用new關鍵字去實例化DB類的對象,是因爲DB類的構造方法使用了private關鍵字進行了封裝。但根據封裝的原則我們可以在類的內部方法中實例化本類的對象,所以聲明瞭一個getInstance()方法,並在該方法中實例化本類的對象。但成員方法也是需要對象才能訪問的,所以在getInstance()方法前使用static關鍵字修飾,成爲靜態方法就不使用對象,而是通過類名來訪問了。如果調用一次getInstance()方法,就在該方法內實例化一次本類對象,這並不是我們想要的結果。所以就需要聲明一個成員屬性$obj,將實例化的對象引用賦值給它,再判斷該變量,如果已經有值,就直接返回,如果值是null,就去實例化對象,這樣就能保證DB類只被實例化一次。又因爲getInstance()方法是static修飾的靜態方法,靜態方法又不能訪問非靜態的成員,所以成員屬性$obj也必須是一個靜態成員,而且又不能讓外部類直接訪問,所以也需要使用private關鍵字封裝起來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章