2011-08-18 42 views
22

我們最近有一個討論,如果有可能建立一個trait SingletonPHP Traits,我們發揮它圍繞一個可能實現,但遇到了問題,與建築之一。建立一個Singleton特質與PHP 5.4

這是一個學術活動。我知道Singletons have very little - if not to say no - use in PHPone should 'just create one'只是探索特質的可能性:

<?php 
trait Singleton 
{ 
    protected static $instance; 
    final public static function getInstance() 
    { 
     return isset(static::$instance) 
      ? static::$instance 
      : static::$instance = new static; 
    } 
    final private function __construct() { 
     static::init(); 
    } 
    protected function init() {} 
    final private function __wakeup() {} 
    final private function __clone() {}  
} 

class A { 
    use Singleton; 
    public function __construct() { 
     echo "Doesn't work out!"; 
    } 
} 

$a = new A(); // Works fine 

重現:http://codepad.viper-7.com/NmP0nZ

的問題是:它可以創建一個Singleton性狀的PHP?我們發現

+0

我敢打賭,downvote/s是/是僅僅因爲你用這個詞「單身」。 –

回答

27

快速解決方案(感謝聊天!):

如果性狀和類都定義了相同的方法,類,如果使用

所以辛格爾頓只特質的作品一個如果使用它的類沒有定義一個__construct()

特點:

<?php 
trait Singleton 
{ 
    protected static $instance; 
    final public static function getInstance() 
    { 
     return isset(static::$instance) 
      ? static::$instance 
      : static::$instance = new static; 
    } 
    final private function __construct() { 
     $this->init(); 
    } 
    protected function init() {} 
    final private function __wakeup() {} 
    final private function __clone() {}  
} 

例如,對於消費類:

<?php  
class A { 
    use Singleton; 

    protected function init() { 
     $this->foo = 1; 
     echo "Hi!\n"; 
    } 
} 

var_dump(A::getInstance()); 

new A(); 

的的var_dump現在產生預期的輸出:

Hi! 
object(A)#1 (1) { 
    ["foo"]=> 
    int(1) 
} 

和新的失敗:

Fatal error: Call to private A::__construct() from invalid context in ... 

Demo

+0

方法「init」將被稱爲靜態,但它不是。 –

+0

我看你自從mabe的評論以來你一定已經做了'init'靜態的。你最好把它作爲一個常規的保護方法,並用'$ this'來調用它,否則你將無法啓動實例變量。 – RobMasters

+0

@RobMasters根據代碼改編 – edorian

1

事情是th在getInstance類型中,返回值將會很模糊,因爲它取決於消費者。這給出了一個弱類型的方法簽名。 例如,它不可能在getInstance方法doc塊中提供符合消費者類型的@return。

2

我創建了一個前一陣子,當我很無聊努力學習特點。它使用反射和__CLASS__不斷

特點:

trait Singleton 
{ 
private static $instance; 

public static function getInstance() 
{ 
    if (!isset(self::$instance)) { 
     $reflection  = new \ReflectionClass(__CLASS__); 
     self::$instance = $reflection->newInstanceArgs(func_get_args()); 
    } 

    return self::$instance; 
} 
final private function __clone(){} 
final private function __wakeup(){} 
} 

這樣您就可以繼續使用__construct()方法,不需要使用任意功能的構造。

1

這傢伙所有你所需要的。 如果你希望你可以使用私人靜態成員,但沒有真正的需要...... 測試工作儘管你可能會認爲靜態的將是全球或東西:)

trait Singleton 
{ 
    /** 
    * Singleton pattern implementation 
    * @return mixed 
    */ 
    public static function Instance() 
    { 
     static $instance = null; 
     if (is_null($instance)) { 
      $instance = new self(); 
     } 
     return $instance; 
    } 
} 

用法:

class MyClass 
{ 
use Singleton; 
}