2011-08-18 4 views
22

trait SingletonPHP Traitsをビルドすることができたかどうかについて議論しましたが、可能なインプリメンテーションで試してみましたが、ビルド1で問題が発生しました。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

ある質問:PHPでのシングルトン形質を作成することは可能でしょうか?私たちが発見した

+0

"シングルトン"。 –

答えて

27

クイックソリューションは、(おかげでチャット!):

トレイトとクラスの両方が同じメソッドを定義する場合、

ので、シングルトンの形質が作品だけ使用した場合、クラスの1

<?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() {}  
} 

:それを使用するクラスは__construct()

形質を定義していない場合消費クラスの例:

<?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

事あなたはgetInstanceの型では、消費者に依存するため、リターンはあいまいになります。これは弱い型のメソッドシグネチャを与えます。 たとえば、getInstanceメソッドのdoc blocでコンシューマ型に準拠した@returnを提供することができません。

2

私は少し前に、私は形質を勉強しようと疲れたときに作成しました。あなたが__construct()メソッドを使用し続けることができますし、コンストラクタとして任意の関数を使用する必要はありません

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(){} 
} 

この方法:それは反射と__CLASS__定数

形質を使用しています。

1

これは皆必要なものです。 あなたはプライベートな静的メンバーを使うことができますが、本当の必要はありません...テスト済み 、あなたは静的なグローバルまたは何か:)

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

使い方になると思うかもしれないという事実にもかかわらず動作します:私はあなたが単語を使用という理由だけで/ sのdownvoteが/あるさ賭ける

class MyClass 
{ 
use Singleton; 
} 
関連する問題