比如我有一個類,類名是A(這個類本身不是實現單例模式的,看後面執行個體化這個類的方式):
class A(){ public $str = '這是屬性'; public $str2 = '屬性'; private $str3 = '私人屬性'; public function __construct($a,$b,$c){ //構造方法 } public function func1(){ //類的方法 } public function func2(){ //類的方法 }}
還有一個全域函數:
function getObj(){ require PATH.'a.class.php';//引入上面定義的class A的檔案 static $instance;//定義靜態變數 if($instance){ return $instance; } $instance = new A('1','2','3'); return $instance;}
然後我要在其他地方調用類A的執行個體,並且可能需要一次請求調用多次,通過getObj方法來得到這個類的執行個體,因為是返回的靜態變數,其實在第一次建立這個類的執行個體後,後面調用都是直接用的這個靜態變數的執行個體,並沒有重新new一個新的執行個體,這種方式算不算單例模式??如果不算,主要是哪裡不同會有什麼隱患??十分感謝!
回複內容:
比如我有一個類,類名是A(這個類本身不是實現單例模式的,看後面執行個體化這個類的方式):
class A(){ public $str = '這是屬性'; public $str2 = '屬性'; private $str3 = '私人屬性'; public function __construct($a,$b,$c){ //構造方法 } public function func1(){ //類的方法 } public function func2(){ //類的方法 }}
還有一個全域函數:
function getObj(){ require PATH.'a.class.php';//引入上面定義的class A的檔案 static $instance;//定義靜態變數 if($instance){ return $instance; } $instance = new A('1','2','3'); return $instance;}
然後我要在其他地方調用類A的執行個體,並且可能需要一次請求調用多次,通過getObj方法來得到這個類的執行個體,因為是返回的靜態變數,其實在第一次建立這個類的執行個體後,後面調用都是直接用的這個靜態變數的執行個體,並沒有重新new一個新的執行個體,這種方式算不算單例模式??如果不算,主要是哪裡不同會有什麼隱患??十分感謝!
接下去就要是PHP7的時代了,你的代碼還停留在看上去像是5.x早期時代的PHP代碼,本身代碼應該可以跑通,你的使用方式從寬泛的定義上來講,勉強可以算單例,但是整體感覺非常奇怪。並且如別的回答提出的,如果別人不知道getObj函數的話,很有可能就自己new了,你的擷取對象的函數無法對別人起到約束作用
既然你的建構函式依賴三個參數,這是我對於這份代碼的建議實現
class A(){ public $str = '這是屬性'; public $str2 = '屬性'; private $str3 = '私人屬性'; private static $pool = []; public static function getInstance($a, $b, $c) { /** * 這裡假設一種情況是需要這三個參數這個對象才唯一 * 並且這三個參數都是可以轉換為字串類型的 *(也就是說不能是stream,array,或者沒有__toString()實現的object) */ $key = implode('_', func_get_args()); if (!isset(self::$pool[$key])) { /** * 關於這裡使用static關鍵字詳情請看後期靜態繫結 * http://php.net/manual/zh/language.oop5.late-static-bindings.php * 如果你的PHP還在用5.3以前的版本,請使用 * self::$pool[$key] = new self($a, $b, $c); */ self::$pool[$key] = new static($a, $b, $c); } return self::$pool[$key]; } protected function __construct($a, $b, $c) { //構造方法,沒有使用private是考慮如果有子類繼承的情況 } public function func1() { //類的方法 } public function func2() { //類的方法 }}
PS 另外建議題主去瞭解一下PSR規範和autoload
會報錯的,而且這種寫法很糟糕
其實不算。原因如下:
1.假設是多線程的環境,多個線程同時進入會不會同時產生多個對象呢,所以需要你進行冗餘處理。我不知道php是怎麼做的,但是Java可以通過sync關鍵字來搞定同步。
2.你建構函式是公有的,假設別人在你的代碼上二次開發,但他不知道你的這個getobj。他就會自己new一個。這樣也會有問題。