[POO] Factorisation des méthodes d'un singleton
Bonjour à tous !
Ceci étant mon premier post ici [edit: j'ai déjà posté une fois, m'en rappelais plus... :d ], je tiens tout d'abord à remercier Développez pour la masse incroyable de cours et d'infos disponibles (marre des bouquins aux prix exorbitants pour un contenu plus que médiocre...)
Venons-en au fait, je cherche à créer une classe abstraite Singleton qui pourrait être étendue par d'autres classes afin de factoriser le code de getInstance() et les diverses exceptions levées (lors d'un clonage, par ex.).
J'ai donc le code suivant pour ma classe Singleton :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php
require("getCalledClassFix.php"); // http://fr.php.net/manual/en/function.get-called-class.php#92845 en attendant PHP 5.3 sur Ubuntu...
abstract class Singleton {
private static $instance;
public static function getInstance()
{
$cls = get_called_class();
if (!isset(self::$instance)) self::$instance = new $cls();
return self::$instance;
}
// Prevent cloning
public function __clone()
{
throw new SingletonException(__CLASS__ . ' : cloning not allowed');
}
}
class SingletonException extends Exception
{
}
?> |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php
final class Config extends Singleton {
protected static $instance;
private $params = array();
protected function __construct()
{
include("config.php");
$this->params['server'] = $server;
$this->params['username'] = $username;
$this->params['password'] = $password;
$this->params['db'] = $db;
}
}
class ConfigException extends Exception
{
}
?> |
Le problème est que je n'arrive pas à dériver cette classe sur une deuxième classe en même temps. Si je crée une classe DBLink (avec disons la même construction que Config...),et que je récupère une instance de chaque classe, j'obtiens un object Config et non DBLink...
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
$bar = Config::getInstance();
$foo = DBLink::getInstance();
var_dump($bar);
var_dump($foo);
// Output:
// object(Config)[1]
// private 'params' =>
// array
// empty
//
// object(Config)[1]
// private 'params' =>
// array
// empty |
Il me semble bien évident que le problème vient de "self::$instance" dans ma classe Singleton, qui se réfère à Singleton::$instance et non à Config::$instance ou DBLink::$instance...
Existe-t-il une méthode pour que "self" dans la classe mère fasse en fait référence aux propriétés de la classe dérivée ? Ou suis-je lancé dans une impasse, et je dois me résigner à redéclarer getInstance dans chaque classe de type Singleton ?
Merci d'avance pour vos lumières :)