<?php /** * 【單例模式】 * 總結:防止外部new物件;防止子類繼承;防止克隆。 */ header("Content-type: text/html; charset=utf-8"); /******* NO.1 普通的可以呼叫的類 ******/ //先定義一個類,例項化兩次,看看是否全等(===) class sigleA{ } $sa1 = new sigleA(); $sa2 = new sigleA(); //注意:當兩個物件是一個的時候,才會全等 //此處輸出 “sa-不是一個物件” if($sa1 === $sa2){ echo 'sa-是一個物件<br>'; }else{ echo 'sa-不是一個物件<br>'; } /********************* NO.2 封鎖new操作 ********************/ //getIns 預先判斷例項 class sigleB{ protected static $ins = null; public static function getIns(){ //getIns 獲取例項 if(self::$ins === null){ //把【自身物件】 賦給 一個自己的 【靜態屬性】 self::$ins = new self(); } return self::$ins; } //保護的 建構函式 protected function __construct(){ } } //再去判斷兩個物件 $sb1 = sigleB::getIns(); $sb2 = sigleB::getIns(); //此處輸出 “sb-是一個物件” if($sb1 === $sb2){ echo 'sb-是一個物件<br>'; }else{ echo 'sb-不是一個物件<br>'; } ////----- 但是,下面用一個新的類繼承自上面的 sigleB ... class multi extends sigleB{ public function __construct(){ } } $m1 = new multi(); $m2 = new multi(); //此處輸出 “m-不是一個物件”,原因在於被繼承後,__construct 被公開了 if($m1 === $m2){ echo 'm-是一個物件<br>'; }else{ echo 'm-不是一個物件<br>'; } /********************* NO.3 final防止繼承 ********************/ class sigleC{ protected static $ins = null; public static function getIns(){ if(self::$ins === null){ self::$ins = new self(); } return self::$ins; } //若方法前加上final,則方法不能被覆蓋; //若類前加上final,則類不能被繼承 final protected function __construct(){ } //同樣的,防止克隆(clone) final protected function __clone(){ } } $sc1 = sigleC::getIns(); $sc2 = clone $sc1; //被克隆了,又產生了多個物件; //如果沒加上 防止克隆的程式碼,此處輸出 “sc-不是一個物件” //上面加上了 final protected function __clone(),這裡就會出錯: //Fatal error: Call to protected sigleC::__clone() from context '' in ... if($sc1 === $sc2){ echo 'sc-是一個物件<br>'; }else{ echo 'sc-不是一個物件<br>'; }