When creating a Singleton in PHP, I ensure that it cannot be instantiated by doing the following:
class Singleton {
private function __construct() {}
private function __clone() {}
public static function getInstance() {}
}
However, I realised that defining a class as 'abstract' means that it cannot be instantiated. So is there anything wrong with doing the following instead:
abstract class Singleton {
public static function getInstance() {}
}
The second scenario allows me to write fewer lines of code which would be nice. (Not that it actually makes much of a difference.)
When creating a singleton in PHP, declaring the __construct
and __clone
as private ensures that the class cannot be instanciated from the outside : it can still be instanciated from inside its declaration.
When declaring a class as abstract
, it can not be instanciated at all ; not even from inside its declaration.
This means your solution would not work : in the second case, your getInstance()
method will not be able to instanciate the class -- while it can do so in the first case.
No because then then you can't instantiate the class at all (not even in the static getInstance method). The private constructor in the singleton example just assures, that only the static getInstance method from the same class can access the constructor.
No, you cannot use an abstract class instead of a private __construct() when creating a singleton. But if your intention is to create an Abstract Singleton from which to extend from, you can do so like this:
abstract class Singleton
{
private static $_instances;
public static function getInstance()
{
$className = get_called_class(); // As of PHP 5.3
if(! isset(self::$_instances[$className] )) {
self::$_instances[$className] = new $className();
}
return self::$_instances[$className];
}
protected function __construct( ) {}
final private function __clone( ) {}
final private function __wakeup( ) {}
}
You can then extend from Singleton like this:
class Foo extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
and
class Bar extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
and manipulating:
$foo1 = Foo::getInstance();
$foo1->setFoo(5);
$foo2 = Foo::getInstance();
var_dump($foo2);
$bar1 = Bar::getInstance();
var_dump($bar1);
echo new ReflectionObject($foo2);
echo new ReflectionObject($bar1);
However, keep in mind that Singletons are very hard to unit-test and should be avoided if possible. See my answer here for some background:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With