2012-01-18 87 views
0

我有最后的静态方法 “的getInstance()” 单例类:PHP 5.3抽象单身班和儿童?

<?php 

abstract class Singleton 
{ 
    protected static $instances; 

    final public static function getInstance() 
    { 
     $class = get_called_class(); 

     if(!isset(static::$instances[$class])) 
      static::$instances[$class] = new $class(); 

     return static::$instances[$class]; 
    } 
} 

而且这样的代码:

<?php 

class C1 extends Singleton { } 
class C2 extends Singleton { } 

C1::getInstance(); // Created C1 class 
C2::getInstance(); // Still get C1 class, get_called_class() return C1 when i try get C2 

什么我做错了什么?

+5

您使用的一个开始:) – GordonM 2012-01-18 08:58:38

+1

单身[看起来工作得很好(http://codepad.viper-7.com/BlBDGC)。 – cmbuckley 2012-01-18 09:20:01

回答

1
C1->getInstance(); 
C2->getInstance(); 

应该

C1::getInstance(); 
C2::getInstance(); 

The code

更新: 您不需要一个数组来保存实例,而是让子类保持。尝试下面的代码。

class Singleton 
{ 
    private function __construct(){} 

    protected static $instance; 

    final public static function getInstance() 
    { 
     $class = get_called_class(); 
     if(!static::$instance) 
      static::$instance = new $class(); 

     return static::$instance; 
    } 
} 

class C1 extends Singleton { 
    protected static $instance; 
} 
class C2 extends Singleton { 
    protected static $instance; 
} 

var_dump(C1::getInstance()); 
var_dump(C2::getInstance()); 
+0

对不起,我的错。无论如何,当我调用C2 :: getInstance()时,我还是得到了C1。 – CSharpRU 2012-01-18 09:17:32

+0

@ user1155760您是否看到了键盘?我只是复制你的代码并获得C2。 – xdazz 2012-01-18 09:22:01

+0

是的,但本地仍然获得C1。 – CSharpRU 2012-01-18 09:23:43

2

这不起作用的原因是你没有为你的每个子类创建一个$ instance属性。虽然使用static ::和get_called_class()将访问子类成员而不是超类成员,但如果成员不存在于子类中,则它们将回退到超类中定义的成员。这样做的结果就是你最终会得到同样的成员。

尝试像这样定义你的子类。

class C1 extends Singleton { 
    protected static $instances; 
} 

class C2 extends Singleton { 
    protected static $instances; 
} 
1

试试这个抽象辛格尔顿:

abstract class Singleton 
{ 
    private static $_instances = array(); 

    public static function getInstance() 
    { 
     $class = get_called_class(); 
     if (!isset(self::$_instances[$class])) { 
      self::$_instances[$class] = new $class(); 
     } 
     return self::$_instances[$class]; 
    } 
} 
+0

+1'self'关键字在这里更有意义。 – cmbuckley 2012-01-18 09:22:48

0

我无法重现你的问题:

var_dump(C1::getInstance()); 
var_dump(C2::getInstance()); 

给出:

object(C1)#1 (0) { 
} 
object(C2)#2 (0) { 
} 

由于var_dump输出显示,类型不同(C1,然后C2)。请记住,您需要静态调用getInstance(),因为它是一个静态函数。

接下来,如果你想真正在PHP中实现Singleton模式,那么你的抽象类缺少一些重要的方法定义,以便使用PHP更加精确。请参阅Patterns­PHP Manual

另外在PHP中,你通常不需要单例,而是注入依赖,这会使你的代码更加流畅。

希望这是有帮助的。

0

工作抽象单的版本:

abstract class Singletone { 
    private static $_instance = NULL; 

    private function __construct(){} 

    public static function GetInstance() { 

     if(!static::$_instance) { 
      static::$_instance = new static(); 
     } 
     return static::$_instance; 
    } 
} 

派生类必须覆盖$ _instance

class DefaultRouter extends Singletone { 
    protected static $_instance = NULL; 
} 
0

有没有必要重新定义静态的$instance属性的子类,只需要使用一个定义在超类中:

<?php 
class Singleton 
{ 
    public static $Instance; 

    private function __construct() { } 

    public static function GetInstance() { 

     if(!Singleton::$Instance) { 
      Singleton::$Instance = new static(); 
     } 
     return Singleton::$Instance; 
    } 
} 

class MyClass extends Singleton 
{ 
    public $field1; 
    public $field2; 
    public $field3; 

    public function __construct() 
    { 
     $this->field1 = "field1"; 
     $this->field2 = "field2"; 
     $this->field3 = "field3"; 
    } 
} 

var_dump(Myclass::GetInstance()); 
?> 

它输出

object(MyClass)#1 (3) { 
    ["field1"]=> 
    string(6) "field1" 
    ["field2"]=> 
    string(6) "field2" 
    ["field3"]=> 
    string(6) "field3" 
} 

https://eval.in/306503