简体   繁体   中英

PHP 5.3 Abstract singleton class and childrens?

i has singleton class with final static method "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];
    }
}

And code like this:

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

What i'm do wrong?

The reason this isn't working is that you're not creating a $instance property for each of your subclasses. While using static:: and get_called_class() will access subclass members instead of superclass members, if the members don't exist in the subclass then they will fall back to the ones defined in the superclass. The result of this is that you'll end up getting the same member anyway.

Try defining your subclasses like this instead.

class C1 extends Singleton { 
    protected static $instances;
}

class C2 extends Singleton { 
    protected static $instances;
}

Try this abstract 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];
    }
}
C1->getInstance();
C2->getInstance();

should be

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

The code

Update: You don't need an array to hold the instances, instead, let the subclass the hold. Try the code below.

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());

Working version of abstract singleton:

abstract class Singletone {
    private static $_instance = NULL;

    private function __construct(){}

    public static function GetInstance() {

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

The derived class must overwrite the $_instance

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

There's no need to redefine the static $instance property in the child classes, just use the one defined in the superclass:

<?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());
?>

It outputs

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

https://eval.in/306503

I can't reproduce your problem:

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

gives:

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

As the var_dump output shows, the types are different ( C1 , then C2 ). Keep in mind that you need to invoke the getInstance() statically as it's a static function.

Next to that if you want to really implement the Singleton pattern in PHP, your abstract class is missing some important method definitions to make this more precise with PHP. See Patterns PHP Manual .

Also in PHP you normally do not need a Singleton at all, inject dependencies instead which will make your code more fluent.

Hope this is helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM