Le design pattern Singleton
Description
Le design pattern Singleton a pour but d’assurer qu’une classe ne possède qu’une seule instance en mémoire et de fournir une méthode de classe retournant cette instance unique.
Dans certains cas, il peut s’avérer utile de gérer des classes ne possédant qu’une seule instance. Dans le cadre des design patterns de construction, nous pouvons citer le cas de la fabrique de produits (Abstract Factory) dont il n’est pas nécessaire de créer plus d’une instance.
Exemple
Dans le système de vente en ligne de véhicules, nous devons gérer des classes possédant une seule instance.
Le système de liasse de documents destinés au client lors de l’achat d’un véhicule (comme le certificat de cession, la demande d’immatriculation et le bon de commande) utilise la classe LiasseVierge qui ne possède qu’une seule instance. Cette unique instance référence tous les documents nécessaires pour le client. Elle est appelée la liasse vierge car les documents qu’elle référence sont tous vierges. L’utilisation complète de la classe LiasseVierge est expliquée dans le chapitre précédent, consacré au design pattern Prototype.
La figure 8.1 illustre l’utilisation du design pattern Singleton pour la classe LiasseVierge. L’attribut statique instance contient soit null soit l’unique instance de la classe LiasseVierge. La méthode de classe getInstance renvoie cette unique instance contenue dans l’attribut instance. Si cet attribut est à null, il est initialisé lors de la création de l’unique instance.
Figure 8.1 - Le design pattern Singleton appliqué à la classe LiasseVierge
Structure
1. Diagramme de classes
La figure 8.2 détaille la structure générique du design pattern Singleton.
Figure 8.2 - Structure du design pattern Singleton
2. Participants
Le seul participant est la classe Singleton qui offre l’accès à l’unique instance par sa méthode de classe getInstance.
Par ailleurs, la classe Singleton possède un mécanisme qui assure qu’elle ne peut posséder au plus qu’une seule instance. Ce mécanisme bloque toute tentative de création d’autres instances.
3. Collaboration
Chaque client de la classe Singleton accède à l’unique instance par la méthode de classe getInstance. Il ne peut pas créer de nouvelles instances en utilisant l’opérateur habituel d’instanciation (opérateur new), qui n’est plus accessible car sa visibilité est dorénavant privée. De même, la méthode magique __clone peut aussi se voir attribuer un mode d’accès privé afin d’interdire au code client de contourner le verrouillage mis en place au niveau du constructeur en tentant de créer des clones du singleton. Nous avons ici choisi de la laisser publique mais de lever une exception pour signaler que cette méthode ne peut pas être invoquée.
Domaine d’utilisation
Le design pattern Singleton est utilisé dans les cas suivants :
-
Il ne doit y avoir qu’une seule instance d’une classe résidant en mémoire.
-
Cette instance ne doit être accessible qu’au travers d’une méthode de classe.
Exemples en PHP
1. La liasse vierge
Le code PHP complet de la classe LiasseVierge est donné dans le chapitre du design pattern Prototype. La partie de cette classe relative à l’utilisation du design pattern Singleton est fournie à la suite.
Le constructeur de cette classe a une visibilité privée afin que seule la méthode getInstance puisse l’utiliser. Ainsi, aucun objet externe à la classe LiasseVierge ne peut créer d’instance en utilisant l’opérateur new.
De la même façon, l’attribut instance possède également une visibilité privée pour que l’accès ne soit possible que depuis la méthode de classe getInstance.
<?php
declare(strict_types=1);
namespace ENI\DesignPatterns\Prototype;
class LiasseVierge extends AbstractLiasse
{
private static ?self $instance = null;
public static function getInstance(): self
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function ajoute(AbstractDocument $document): void
...