PHP 5.3摘要单例类和子类?

时间:2012-01-18 08:57:21

标签: php singleton

我的单例类有最终的静态方法“getInstance()”:

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

我做错了什么?

6 个答案:

答案 0 :(得分:2)

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

尝试定义这样的子类。

class C1 extends Singleton { 
    protected static $instances;
}

class C2 extends Singleton { 
    protected static $instances;
}

答案 1 :(得分:1)

试试这个抽象的Singleton:

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];
    }
}

答案 2 :(得分: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());

答案 3 :(得分: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中,您通常根本不需要Singleton,而是注入依赖项,这将使您的代码更流畅。

希望这有用。

答案 4 :(得分: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;
}

答案 5 :(得分: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