Adaptation du pattern Singleton à plusieurs instances (PHP et AS2)
Par -Alexandre LEGOUT aka LAlex- le 20 avril 2004, 09:24 - PHP - Lien permanent
Le pattern Singleton est trés souvent une bonne alternative à l'utilisation de classes possédant uniquement des méthodes statiques. Il permet de n'instancier qu'une seule fois une classe, et d'accéder toujours à cette même instance au moyen d'une méthode statique. Une brillante explication a déjà été faite par petepx dans son ticket DESIGN PATTERNS #1.
Sur le même principe, lors de la création de mon moteur de blog, je voulais économiser le plus possible de requêtes SQL, et donc éviter d'instancier deux fois le même objet. Par exemple, pour un ticket, il peut appraître trois fois sur la page d'accueil, dans des templates (et donc des scripts PHP) différents :
- Dans le menu "Dernières entrées"
- Dans le menu "Derniers commentaires"
- Dans le contenu principal
Comme tout enregistrement d'une base de données bien concue, chaque ticket possède évidemment un identifiant unique, qui va alors me servir à distinguer le ticket que je veux en transmettant cet identifiant à ma méthode statique. Cet identifiant va également servir d'indice pour une propriété de type tableau stockant toutes les instances déjà créées.
Voici comment cela se présente en PHP4, qui je vous le rappelle n'offre pas la possibilité de faire des propriétés statiques. Il faut donc contourner cette limitation par l'utilisation de variables globales :// Déclaration de la classe
Voici ce que cela donnerait en AS2 :
class Ticket {
// Identifiant du ticket
var $_id;
// Fonction constructeur
// Accés "private"
function Ticket($id = 0) {
if ($id > 0) {
$this->_id = (int)$id;
}
}
// Methode getInstance
// Retourne une référence vers l'instance
// correspondant à l'identifiant
function &getInstance($id) {
// Si l'indice n'est pas numérique, ne retourne rien
if (!is_numeric($id)) {
return;
}
// Teste l'existance de la propriété "statique"
if (!isset($GLOBALS["INSTANCES_TICKETS"])) {
$GLOBALS["INSTANCES_TICKETS"] = Array();
}
// Teste si l'instance demandée est déjà créée
// Si ce n'est pas le cas, la classe est instanciée
if (!isset($GLOBALS["INSTANCES_TICKETS"][(int)$id])) {
$GLOBALS["INSTANCES_TICKETS"][(int)$id] = new Ticket($id);
}
// Retourne l'instance
return $GLOBALS["INSTANCES_TICKETS"][(int)$id]
}
}
// Utilisation
$monTicket =& Ticket::getInstance(124);class Ticket {
// Identifiant du ticket
private var _id:Number;
// Tickets instanciés
private static var _lstInstances:Array = new Array();
// Fonction constructeur
private function Ticket($id:Number) {
if ($id != undefined) {
this._id = Number($id);
}
}
// Méthode statique getInstance
public static function getInstance($id:Number):Ticket {
if ($id == undefined) {
return;
}
// Si l'instance demandée n'existe pas, on la crée
if (_lstInstances[$id] == undefined) {
_lstInstances[$id] = new Ticket($id);
}
// On retourne l'instance
return _lstInstances[$id];
}
}
// Utilisation
var monTicket = Ticket.getInstance(124);
Suite à cela, j'accède aux propriétés de mon ticket via des getters, qui vérifient auparavant si l'instance à bien été remplie depuis la base de données (ou depuis un XML, ou depuis un requete serveur dans le cas de Flash). Ainsi, au premier accés, les propriétés de l'objet sont renseignées, et les accés suivants se font toujours sur la même instance ! ![]()
Commentaires
Merci
salut
mais il y a petite erreur de logique dans la partie AS2
L'instance doit etre créer si elle est undefined et non le contraire.
vraiment pratique ce Singleton...
A+
Oups ...
Wala, c'est rectifié ! 
ça s'appelle pas le "poids-plume" ça comme pattern ?
funkC >> Aucune idée !
Ce ne serait pas étonnant que ce pattern existe déjà, et donc qu'il ai déjà un nom ! 
++ ^^
salut
il me semble que les 2 sont la meme choses
Anglais : Singleton
Francais : poids-plume
j'aime définitivement mieu le terme Singleton
Pareil
l'autre... on dirait que l'on va assister à un match de boxe 
lol que le meilleur gagne
Cool LAlex !
Sinon le poids-plume ou poids mouche n'est pas un pattern Singleton, mais une classe composite avec un composant en membre statique à l'intérieur (composant Singleton). Le poids mouche permet à ses multiples instances d'exploiter les ressources read-only du composant statique et fournit à chacune d'elles des membres uniques pour le manipuler.
Ce pattern est utilisé pour économiser des ressources machine en évitant de dupliquer un objet lourd en instances multiples. Il encapsule les données de celui-ci dans un membre statique de la classe et fournit des fonctionnalités pour y accéder de façons multiple et donner l'illusion de bien manipuler un parc d'instances uniques.
Je sais pas si j'ai été très clair sur ce coup. ^^
Très clair.. car c'est marrant j'utilise cette technique sans savoir qu'elle portait ce nom
merci pour l'infos petepx!
petepx > En gros, si j'ai bien compris, on crée une propriété statique contenant un objet issu du pattern Singleton, et on implémente dans la classe des méthoides pour accéder aux méthodes de la propriété statique, c'est bien ca ? :o
++ ^^
oui tout à fait
Bonjour,
absolument pas d'accord avec le fait que php n'ai pas de propriété statique. Voici un exemple de méthode qui permet de contourner l'utilisation de globales:
function &getInstance(){
static $instance;
if(is_null($instance){
$instance=new Ticket();
}
return $instance;
}
}
Metal3d > Si tu as bien lu le post, tu a du te rendre compte que je parlais de PHP4 !
Fil des commentaires de ce billet