Patron Singleton
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 71 sur 91.
Le pattern Singleton est un patron de conception de création qui garantit qu'une classe n'a qu'une seule instance tout au long du cycle de vie de votre application. Il fournit également un point d'accès global à cette instance.
Ce patron est utile lorsque vous avez besoin d'exactement un seul objet pour coordonner les actions à travers le système, tel qu'une connexion à une base de données, un gestionnaire de configuration ou un système de journalisation (logger). Créer plusieurs instances de ceux-ci gaspillerait des ressources ou causerait un comportement incohérent.
Voici comment implémenter un Singleton en PHP :
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Le constructeur privé empêche l'instanciation directe
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
Sortie :
Same instanceLe patron repose sur trois éléments clés : un constructeur privé qui empêche d'utiliser new directement, une propriété statique qui détient l'instance unique, et une méthode statique qui crée l'instance lors du premier appel et la retourne lors des appels suivants.
Pour rendre le Singleton véritablement robuste, vous devriez également empêcher le clonage et la désérialisation :
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Défi
FacileConstruisons un gestionnaire de configuration en utilisant le Singleton Pattern. Dans les applications réelles, vous souhaitez généralement une source de vérité unique pour les paramètres de configuration — avoir plusieurs objets de configuration pourrait entraîner un comportement incohérent dans votre système.
Vous organiserez votre code sur deux fichiers :
Config.php— Créez une classeConfigqui implémente le Singleton Pattern. Votre gestionnaire de configuration doit :- Stocker les paramètres dans une propriété de type tableau privée
- Avoir un constructeur privé qui initialise le tableau de paramètres comme vide
- Fournir une méthode statique
getInstance()qui retourne l'instance unique - Empêcher le clonage en rendant
__clone()privé - Inclure une méthode
set(string $key, string $value): voidpour stocker un paramètre - Inclure une méthode
get(string $key): ?stringqui retourne la valeur pour une clé, ounullsi la clé n'existe pas - Inclure une méthode
getAll(): arrayqui retourne tous les paramètres
main.php— Incluez le fichier Config. Vous recevrez deux entrées : une clé et une valeur.Récupérez l'instance de Config et définissez un paramètre par défaut avec la clé
"app_name"et la valeur"MyApp".Récupérez une deuxième référence à l'instance de Config (en utilisant à nouveau
getInstance()) et utilisez-la pour définir un autre paramètre en utilisant la clé et la valeur provenant des entrées.Enfin, vérifiez que le Singleton fonctionne correctement :
- Affichez
"Same instance: true"ou"Same instance: false"selon que les deux références pointent vers le même objet (utilisez===pour comparer) - Affichez
"Settings count: [count]"montrant le nombre total de paramètres stockés (utilisezcount()sur le résultat degetAll()) - Affichez
"App name: [value]"montrant le paramètre app_name récupéré via la deuxième référence
- Affichez
Ce défi démontre l'avantage principal du Singleton Pattern : peu importe le nombre de fois que vous appelez getInstance(), vous obtenez toujours le même objet, garantissant que toutes les parties de votre application partagent le même état de configuration.
Aide-mémoire
Le Singleton Pattern (ou patron de conception Singleton) garantit qu'une classe n'a qu'une seule instance tout au long du cycle de vie de votre application et fournit un point d'accès global à cette instance.
Ce patron est utile pour des objets tels que les connexions aux bases de données, les gestionnaires de configuration ou les journaux (loggers), où plusieurs instances gaspilleraient des ressources ou causeraient un comportement incohérent.
Implémentation de base du Singleton :
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Le constructeur privé empêche l'instanciation directe
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
// Résultat : Same instance
Éléments clés :
- Constructeur privé — empêche l'utilisation directe de
new - Propriété statique — contient l'instance unique
- Méthode statique — crée l'instance lors du premier appel et la retourne lors des appels suivants
Empêcher le clonage et la désérialisation :
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Essayez vous-même
<?php
require_once 'Config.php';
// Lire l'entrée
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Obtenir l'instance de Config et définir "app_name" sur "MyApp"
// TODO: Obtenir une deuxième référence à Config en utilisant à nouveau getInstance()
// TODO: Utiliser la deuxième référence pour définir le paramètre en utilisant $key et $value de l'entrée
// TODO: Vérifier que le Singleton fonctionne :
// - Afficher "Same instance: true" ou "Same instance: false" basé sur la comparaison ===
// - Afficher "Settings count: [count]" montrant le nombre total de paramètres
// - Afficher "App name: [value]" montrant app_name récupéré via la deuxième référence
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie