image de chargement
Retour au glossaire

Singleton

Pattern de conception garantissant qu'une classe n'a qu'une seule instance globale avec un point d'accès unique.

Mis à jour le 10 janvier 2026

Le Singleton est un pattern de conception créationnel qui garantit qu'une classe ne possède qu'une seule instance tout au long du cycle de vie d'une application, tout en fournissant un point d'accès global à cette instance. Ce pattern est utilisé pour contrôler l'accès à des ressources partagées comme des connexions de base de données, des gestionnaires de configuration ou des services système.

Fondements du Pattern Singleton

  • Constructeur privé empêchant l'instanciation directe de la classe
  • Variable statique privée stockant l'unique instance de la classe
  • Méthode statique publique (getInstance) retournant toujours la même instance
  • Initialisation paresseuse (lazy loading) ou immédiate selon les besoins

Avantages du Singleton

  • Garantit un contrôle strict sur l'accès à une ressource partagée unique
  • Économise la mémoire en évitant la création d'instances multiples
  • Fournit un point d'accès global simplifié à l'instance
  • Permet l'initialisation différée pour optimiser les performances
  • Facilite la coordination entre différents composants de l'application

Exemple Concret en TypeScript

DatabaseConnection.ts
class DatabaseConnection {
  private static instance: DatabaseConnection;
  private connectionString: string;
  private isConnected: boolean = false;

  // Constructeur privé pour empêcher l'instanciation directe
  private constructor() {
    this.connectionString = process.env.DB_URL || '';
  }

  // Méthode publique pour obtenir l'unique instance
  public static getInstance(): DatabaseConnection {
    if (!DatabaseConnection.instance) {
      DatabaseConnection.instance = new DatabaseConnection();
    }
    return DatabaseConnection.instance;
  }

  public connect(): void {
    if (!this.isConnected) {
      console.log(`Connexion à: ${this.connectionString}`);
      this.isConnected = true;
    }
  }

  public query(sql: string): void {
    if (this.isConnected) {
      console.log(`Exécution: ${sql}`);
    } else {
      throw new Error('Database not connected');
    }
  }
}

// Utilisation
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();

console.log(db1 === db2); // true - même instance
db1.connect();
db1.query('SELECT * FROM users');

Cet exemple illustre une connexion de base de données implémentée comme Singleton, garantissant qu'une seule connexion est créée et partagée dans toute l'application, évitant ainsi des connexions multiples coûteuses.

Mise en Œuvre du Pattern

  1. Déclarer le constructeur de la classe comme privé pour bloquer l'opérateur new
  2. Créer une propriété statique privée pour stocker l'instance unique
  3. Implémenter une méthode statique getInstance() qui crée l'instance si nécessaire
  4. Gérer la synchronisation dans les environnements multi-threads si applicable
  5. Considérer l'utilisation de modules ES6 pour une approche plus simple en JavaScript moderne

Attention aux Anti-Patterns

Le Singleton est souvent considéré comme un anti-pattern en raison de sa nature globale qui complique les tests unitaires, crée des dépendances cachées et viole le principe de responsabilité unique. Privilégiez l'injection de dépendances et les conteneurs IoC pour gérer les instances partagées dans les applications modernes.

Alternatives et Cas d'Usage

Dans les applications modernes, les modules ES6 en JavaScript/TypeScript agissent naturellement comme des singletons sans nécessiter d'implémentation complexe. Les frameworks d'injection de dépendances comme NestJS, Angular ou Spring proposent des mécanismes de scope 'singleton' plus testables et maintenables.

modern-singleton.ts
// Approche moderne avec module ES6
export class ConfigService {
  private config: Record<string, any>;

  constructor() {
    this.config = {
      apiUrl: process.env.API_URL,
      timeout: 5000
    };
  }

  get(key: string): any {
    return this.config[key];
  }
}

// Export d'une instance unique
export const configService = new ConfigService();

// Utilisation dans d'autres fichiers
import { configService } from './config';
console.log(configService.get('apiUrl'));

Outils et Frameworks Associés

  • InversifyJS - Conteneur d'injection de dépendances pour TypeScript avec support des scopes singleton
  • TSyringe - Lightweight dependency injection pour TypeScript avec décorateurs
  • NestJS - Framework Node.js avec système d'injection de dépendances et providers singleton natifs
  • Awilix - Conteneur IoC performant pour Node.js supportant différents scopes de vie

Conseil Pro

Pour des applications scalables et testables, remplacez les Singletons classiques par l'injection de dépendances. Utilisez des conteneurs IoC pour gérer le cycle de vie des objets avec un scope singleton tout en gardant votre code découplé et facilement testable avec des mocks.

Bien que le Singleton soit un pattern classique reconnu, son utilisation dans les architectures modernes doit être réfléchie. Il reste pertinent pour des cas spécifiques (gestionnaires de ressources, caches, loggers) mais devrait être implémenté via des mécanismes d'injection de dépendances pour préserver la testabilité et la maintenabilité du code à long terme.

L'argentestdéjàsurlatable.

En 1 heure, découvrez exactement combien vous perdez et comment le récupérer.