patternphpMinor
Base class for singletons
Viewed 0 times
classforsingletonsbase
Problem
Even though singletons are bad practice and often unnecessary, I still see many developers using this pattern over and over. Since implementation of this pattern usually requires some common code, I thought we could just make a base class to be extended.
I came up with this so far.
```
/**
* ----------------------------------------------USE EXAMPLE---------------------------------------------------
* @docs example database
I came up with this so far.
<?php
namespace wl;
/**
* @dosc allows only one instance for each extending class
* @example use it for database connection, config setup...
* Be aware, the singleton pattern is consider to be an anti-pattern
* because it can be hard to debug.
* In most cases you do not need to use singleton pattern
* so take a longer moment to think about it before you use it.
*/
class Singleton
{
/**
* holds an single instance of a class
*
* @var array of objects
*/
protected static $instance = [];
/**
* @desc provides a single slot to hold an instance interchanble between all child classes.
* @return object
*/
public static function getInstance(){
$class = get_called_class();
if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
echo "new ". $class . PHP_EOL; // remove this line after testing
return self::$instance[$class]; // remove this line after testing
}
echo "old ". $class . PHP_EOL; // remove this line after testing
return static::$instance[$class];
}
/**
* do not allow create new instance by new keyword
*
*/
protected function __construct(){}
/**
* Do not clone the object
*/
protected function __clone(){}
/**
* Do not allow reserialization of this object
*/
protected function __wakeup(){}
}```
/**
* ----------------------------------------------USE EXAMPLE---------------------------------------------------
* @docs example database
Solution
Not a Singleton
This is not a singleton. Add the following code:
You have a new
This is a singleton. It will give an error if you try to create a
Is a singleton that gives an error if you create a
Registry
You don't need to use inheritance to get this functionality.
Change to
or just
with
And change
to
Now, it's possible that in a real application you would make more use of what inheritance gives you. But in this toy application, you don't.
I changed the name from
You lose the just-in-time instantiation of the original, but you gain control over how it is instantiated. An advantage of this form is that you can also do things like
Your original form prevented this, exacerbating the Singleton pattern's problems with user testing.
Nitpicks
Without the spelling errors:
I also changed the wording a bit and broke up two lines so that they don't cause scrolling (at least in my browser).
class Database extends Singleton
{
public function __construct(){
}
}This is not a singleton. Add the following code:
$bd7 = new Config();You have a new
Config object. class Config extends Singleton {
protected function __construct() {
}
}This is a singleton. It will give an error if you try to create a
Config object directly. Or class Database extends Singleton {
}Is a singleton that gives an error if you create a
Database object directly as it inherits its constructor from its parent. Registry
You don't need to use inheritance to get this functionality.
public static function getInstance(){
$class = get_called_class();
if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
echo "new ". $class . PHP_EOL; // remove this line after testing
return self::$instance[$class]; // remove this line after testing
}
echo "old ". $class . PHP_EOL; // remove this line after testing
return static::$instance[$class];
}Change to
public static function getInstance($class, $object = null) {
if (!isset(self::$instance[$class]) && $object != null) {
self::$instance[$class] = $object;
}
return static::$instance[$class];
}or just
public static function getInstance($key) {
return static::$instance[$key];
}with
public static function setInstance($key, $object) {
static::$instance[$key] = $object;
}And change
$bd1 = Database::getInstance(); // newto
Registry::setInstance('database', new Database());
$bd1 = Registry::getInstance('database');Now, it's possible that in a real application you would make more use of what inheritance gives you. But in this toy application, you don't.
I changed the name from
Singleton to Registry, as better fitting this pattern. You lose the just-in-time instantiation of the original, but you gain control over how it is instantiated. An advantage of this form is that you can also do things like
Registry::setInstance('database', new MockDatabase());Your original form prevented this, exacerbating the Singleton pattern's problems with user testing.
Nitpicks
/**
* @dosc allows only one instance for each extending class
* @example use it for database connection, config setup...
* Be aware, singleton pattern is consider to be an antipatern and becaouse of it build it is hard to debug.
* In most cases you do not need to use singleton patern so make a longer moment to think about it befor you use it.
*/Without the spelling errors:
/**
* @dosc allows only one instance for each extending class
* @example use it for database connection, config setup...
* Be aware, the singleton pattern is consider to be an anti-pattern
* because it can be hard to debug.
* In most cases you do not need to use singleton pattern
* so take a longer moment to think about it before you use it.
*/I also changed the wording a bit and broke up two lines so that they don't cause scrolling (at least in my browser).
Code Snippets
class Database extends Singleton
{
public function __construct(){
}
}$bd7 = new Config();class Config extends Singleton {
protected function __construct() {
}
}class Database extends Singleton {
}public static function getInstance(){
$class = get_called_class();
if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
echo "new ". $class . PHP_EOL; // remove this line after testing
return self::$instance[$class]; // remove this line after testing
}
echo "old ". $class . PHP_EOL; // remove this line after testing
return static::$instance[$class];
}Context
StackExchange Code Review Q#142630, answer score: 4
Revisions (0)
No revisions yet.