découvrez le design pattern singleton, ses principes fondamentaux et des exemples pratiques en java, c++ et php pour garantir une instance unique de vos classes.

Design pattern Singleton : principe, code en Java, C++ et PHP, limites

Publié par : La rédaction — Rubrique Art & Culture

Mis à jour le

Dans le paysage des patrons de conception, le Singleton occupe une place à part. Décrit en 1994 dans le livre de référence du « Gang of Four » (Design Patterns, de Gamma, Helm, Johnson et Vlissides), c’est un patron de création dont le but tient en une phrase : garantir une instanciation unique d’une classe et fournir un point d’accès global à cet objet. Sa mise en œuvre soulève pourtant de vraies questions de gestion mémoire, de concurrence et d’architecture.

En Java, C++ et PHP, le design pattern s’écrit différemment, mais le principe est le même. On l’utilise typiquement pour un système de journalisation, une configuration centrale, un cache ou un accès à une ressource matérielle. Mal employé, il devient en revanche une variable globale déguisée, qui complique les tests et couple fortement le code.

Exemple typique : une application qui écrit ses logs dans un fichier. Si chaque module crée son propre objet de journalisation, plusieurs objets écrivent dans le même fichier sans se coordonner. Avec un Singleton, tous les modules passent par le même objet, qui gère seul l’accès au fichier.

En bref

  • Le Singleton limite une classe à une seule instance, accessible partout dans le programme.
  • Son intérêt est fort pour les ressources partagées : logs, configuration, cache, connexion à une base.
  • Le principe repose sur un constructeur privé et une méthode statique du type getInstance.
  • La concurrence peut fragiliser une implémentation naïve si elle n’est pas protégée.
  • Des exemples de code en Java, C++ et PHP montrent des variantes adaptées à chaque langage.
  • Ce motif de création doit être utilisé avec mesure, car il peut masquer une architecture trop couplée.

Singleton design pattern : le principe d’une instance unique en Java, C++ et PHP

Un Singleton empêche de créer plusieurs objets là où un seul suffit, et donne à tous les composants un accès au même objet. Il ressemble à une variable globale, avec deux différences : l’objet n’est créé que par la classe elle-même, et il peut n’être créé qu’au premier usage.

Dans un journal d’opérations, par exemple, deux instances pourraient écrire des événements dans un ordre incohérent ou ouvrir deux fois la même ressource. Une instance unique simplifie la cohérence.

Pourquoi une seule instance change la logique d’une application

La question n’est pas seulement technique, elle est aussi architecturale. Pourquoi vouloir un seul objet ? Parce que certaines ressources n’ont aucun intérêt à être répliquées, voire deviennent dangereuses si elles le sont. Un gestionnaire d’impression, un cache de configuration ou un service de journalisation sont des exemples classiques.

Articles en lien :  Indigo : histoire de ce bleu profond et place dans l’art contemporain

Côté code client, on ne fabrique plus l’objet soi-même : on passe par une méthode unique, souvent nommée getInstance.

Pour approfondir l’univers des motifs de conception et leurs usages, un détour par cette lecture sur les usages du Singleton chez les développeurs éclaire bien la logique de centralisation.

Le mécanisme du constructeur privé et de getInstance

La mécanique classique tient en trois éléments. Le constructeur est privé, ce qui interdit new en dehors de la classe. Une méthode statique vérifie si l’instance existe déjà, la crée au besoin, puis renvoie toujours le même objet.

L’instance est conservée dans un attribut statique de la classe, relu à chaque appel.

Élément Rôle dans le Singleton Effet recherché
Constructeur privé Bloque l’instanciation directe Empêche la création sauvage d’objets
Méthode statique getInstance Fournit l’accès à l’objet Offre un point d’entrée unique
Attribut statique Stocke l’unique instance Assure la réutilisation
Initialisation paresseuse Crée l’objet au premier besoin Évite un coût inutile au démarrage

Cette version simple a un défaut : si plusieurs threads appellent getInstance en même temps, ils peuvent créer chacun une instance. C’est le problème de concurrence traité plus bas.

Exemples de code du Singleton en Java, C++ et PHP

Voici des exemples de code courts, dans la forme la plus idiomatique de chaque langage.

Dans chaque cas, on retrouve une classe fermée à la création directe, une instance stockée et un accès contrôlé ; seules changent les garanties offertes par le langage.

Singleton en Java : une instance centrale et lisible

En Java, la version la plus simple et sûre initialise l’instance au chargement de la classe : private static final Logger INSTANCE = new Logger();, un constructeur private Logger() {} et public static Logger getInstance() { return INSTANCE; }. La JVM garantit que l’initialisation d’une classe est faite une seule fois, même avec plusieurs threads.

Pour une création au premier appel, l’idiome du « holder » (une classe interne statique qui contient l’instance) offre la même garantie sans verrou. La double vérification avec verrou est aussi possible, mais l’attribut doit alors être déclaré volatile, faute de quoi elle n’est pas fiable.

Enfin, une énumération à un seul élément, public enum Logger { INSTANCE; }, est la forme recommandée par Joshua Bloch dans Effective Java : elle résiste aussi à la sérialisation et à la réflexion, qui peuvent sinon créer une seconde instance.

Articles en lien :  Paroles de Lola Young messy : analyse et signification

Singleton en C++ : contrôle précis et vigilance sur la gestion mémoire

En C++, la gestion mémoire demande plus d’attention. La forme la plus utilisée aujourd’hui est le « Singleton de Meyers » : une méthode statique qui contient une variable locale statique, static Logger& instance() { static Logger inst; return inst; }. Elle renvoie une référence plutôt qu’un pointeur, ce qui évite de gérer un delete.

L’objet est créé au premier appel et détruit automatiquement à la fin du programme. Depuis C++11, la norme garantit que l’initialisation d’une variable locale statique est thread-safe : pas besoin de verrou. Le point délicat reste l’ordre de destruction, si d’autres objets statiques utilisent le Singleton pendant leur propre destruction.

Il faut aussi interdire les copies, sinon une seconde instance peut apparaître : Logger(const Logger&) = delete; et Logger& operator=(const Logger&) = delete;, en plus d’un constructeur privé.

Singleton en PHP : centraliser sans alourdir l’application

En PHP, on retrouve le même trio : private static ?self $instance = null;, un constructeur privé et public static function getInstance(): self { return self::$instance ??= new self(); }. On rend aussi __clone() privé pour empêcher la duplication par clone.

Une particularité importante : en PHP classique, chaque requête HTTP s’exécute dans un contexte neuf. Le Singleton ne vit donc que le temps d’une requête ; il évite d’ouvrir plusieurs connexions à la base pendant cette requête, mais ne partage rien d’une requête à l’autre. Les frameworks modernes préfèrent d’ailleurs un conteneur d’injection de dépendances, qui fournit un service « partagé » sans Singleton codé en dur.

Pour relier cette logique à d’autres usages concrets, un second éclairage utile se trouve dans cet article sur le rôle du Singleton dans l’outillage des équipes, qui montre comment la centralisation peut aussi servir la maintenance.

Concurrence, erreurs courantes et limites du Singleton design pattern

En mode multithread, deux threads peuvent tester en même temps que l’instance n’existe pas encore, puis la créer chacun de leur côté. L’unicité n’est alors plus garantie.

Les parades dépendent du langage, mais reviennent à s’assurer qu’un seul thread peut créer l’objet :

  • Initialisation dès le chargement : simple et sûre, mais moins souple si l’objet n’est finalement jamais utilisé.
  • Synchronisation de getInstance : efficace contre les doubles créations, au prix d’un léger impact sur les performances.
  • Double vérification : réduit le coût du verrou, mais exige en Java un attribut volatile pour être correcte.
  • Tests unitaires : plus difficiles, car l’état de l’instance persiste d’un test à l’autre et on ne peut pas la remplacer facilement par un faux objet.

Le Singleton peut aussi masquer un couplage excessif : chaque classe qui appelle getInstance() dépend directement d’une implémentation précise, sans que cette dépendance apparaisse dans sa signature.

Articles en lien :  Mise à jour de nos contenus — octobre 2026

Quand le pattern devient une fausse bonne idée

Si un service est utilisé partout, la question à se poser est souvent celle de l’organisation du projet, plutôt que celle de l’accès global.

L’alternative la plus courante est l’injection de dépendances : on crée une seule instance au démarrage et on la passe aux classes qui en ont besoin. On garde l’unicité sans l’accès global, et les tests peuvent fournir un faux objet.

Multiton, variantes et cas d’usage du patron de conception

Autour du Singleton gravitent plusieurs variantes, dont le Multiton. Ici, l’idée change subtilement : il ne s’agit plus d’une seule instance absolue, mais d’une instance par clé. On conserve le principe de contrôle, tout en autorisant plusieurs objets, chacun associé à un identifiant précis.

Cette logique convient, par exemple, à une connexion par base de données ou à un objet par région. Un tableau associatif sert de registre : si la clé existe, l’instance est renvoyée ; sinon, elle est créée et stockée.

Patron Nombre d’instances Cas d’usage fréquent
Singleton Une seule Journalisation, configuration, connexion partagée
Multiton Une par clé Gestion multi-clients, ressources segmentées
Façade Variable Interface simplifiée pour sous-systèmes complexes
Poids mouche Plusieurs, avec états partagés Optimisation d’objets nombreux et légers

Le Singleton se combine aussi avec d’autres motifs. Une Façade est souvent implémentée comme un Singleton, puisqu’un seul point d’entrée suffit. Les fabriques abstraites, les monteurs et les prototypes peuvent eux aussi l’utiliser.

Attention enfin aux systèmes distribués : un Singleton est unique par processus, pas pour toute l’application. Avec plusieurs serveurs ou plusieurs workers, il y aura autant d’instances que de processus ; pour une ressource vraiment unique, il faut un mécanisme externe (base de données, verrou distribué).

Le Singleton est-il adapté à toutes les applications ?

Non. Il convient surtout aux ressources partagées qui doivent rester uniques, comme une configuration centrale, un logger ou une connexion commune. Lorsqu’il devient un contournement pratique à un problème d’architecture, il vaut mieux envisager une autre solution.

Pourquoi le constructeur doit-il être privé ?

Le constructeur privé empêche les créations directes et force le code client à passer par la méthode statique getInstance. C’est ce verrou qui permet de contrôler l’unicité de l’objet.

Le Singleton pose-t-il un problème en concurrence ?

Oui, si l’implémentation est naïve. Deux threads peuvent créer deux instances au même moment. Il faut donc protéger l’accès ou initialiser l’objet de manière sûre selon le langage utilisé.

Quels sont les inconvénients les plus fréquents ?

Le motif peut compliquer les tests, masquer un couplage excessif et rendre certains projets moins flexibles. Il faut donc l’employer avec discernement, surtout dans les architectures évolutives.

Le Singleton existe-t-il différemment en Java, C++ et PHP ?

Le principe reste le même, mais les détails changent. En Java, on privilégie l’initialisation statique ou l’énumération ; en C++, la variable locale statique (thread-safe depuis C++11) et l’interdiction des copies ; en PHP, une propriété statique, sachant que l’instance ne vit que le temps d’une requête.

Auteur/autrice

  • Nuit d'artistes

    La culture au clair de lune : sur Nuit d'artistes, nous prolongeons la visite quand les salles ferment. Expositions, design, artisanat, cinéma, séries, spectacles et festivals : nous décryptons les œuvres et partageons nos découvertes avec curiosité, pour donner envie de sortir et de regarder autrement.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *