php 的單例模式(一)
阿新 • • 發佈:2019-02-14
單例模式,就是保持一個物件只存在一個例項。並且為該唯一例項提供一個全域性訪問點(一般是一個靜態的getInstance方法),單例模式使用的地方很多,一般在資料庫操作物件、日誌寫入物件、全域性配置解析物件等用的比較多。
他們的共同特徵我決定有以下3點:
1.只需要一個例項
2.不斷new多個例項會不斷增加資源的消耗
3.全域性呼叫的話會很便利
單例模式具備的三個關鍵點:
① 需要一個儲存類的唯一例項的靜態成員變數;
②建構函式和克隆函式必須宣告為私有的,防止外部程式new類從而失去單例模式的意義;
③必須提供一個訪問這個例項的公共的靜態方法(通常為getInstance方法),從而返回唯一例項的一個引用 。
我們來寫一個例子來看一下,下面是一個日誌操作類:
class Logger{
//首先,需要一個私有的靜態變數來儲存產生的物件例項
private static $instance;
//業務變數,儲存日誌寫入路徑
private $logDir;
//構造方法,注意必須也是私有的,不允許被外部例項化(即在外部被new)
private function __construct(){
//除錯輸出,測試物件被new的次數
echo "new Logger instance \r\n";
$logDir = sys_get_temp_dir(). DIRECTORY_SEPARATOR . "logs";
if(!is_dir($logDir) || !file_exists($logDir)){
@mkdir($logDir);
}
$this->logDir = $logDir;
}
//類唯一例項的全域性訪問點,用於判斷並返回物件例項,供外部呼叫
public static function getInstance(){
if(is_null(self::$instance)){
$class = __CLASS__; //獲取本物件的型別,也可以用new self()方式
self::$instance = new $class();
}
return self::$instance;
}
//過載__clone()方法,不允許物件對克隆
public function __clone(){
throw new Exception("Singleton Class Can Not Be Cloned");
}
//具體的業務方法,實際可以有很多方法
public function logError($message){
$logFile = $this->logDir . DIRECTORY_SEPARATOR . "error.log";
error_log($message, 3, $logFile);
}
}
//日誌呼叫
$logger = Logger::getInstance();
$logger->logError("An error occured");
$logger->logError("Another error occured");
//或者這樣呼叫
Logger::getInstance()->logError("Still have error");
Logger::getInstance()->logError("I should fix it");
這就是一個單例模式的一個簡單例子。
重點注意:單例濫用,單例模式相對來說比較好理解和實現,因此一旦認識到單例模式的好處,很可能什麼類都想寫成單例,因此在使用次模式之前一定要考慮之前博主說的3種情況,看是否真的有必要使用。