Skip to content

Quelques patrons de conception

Singleton et service locator

  • La technique du singleton permet de manipuler une instance unique
  • Elle peut être mise en place via une propriété ou méthode statique d'une classe qui retourne la même instance de cette classe
  • ⚠ Le constructeur d'une classe singleton est privé, pour interdire l'instanciation depuis du code externe
  • Il est aussi possible de centraliser les singletons dans une seule classe qu'on appelle service locator
  • Le service locator est préféré car il permet de centraliser la gestion des instances et peut apporter des fonctionnalités communes
Propriétés
class Mage {
  private constructor(public name: string, public hp: number) {}

  static readonly instance = new Mage("", 0);
}

Mage.instance.hp = 200;
console.log(Mage.instance.hp);

class Thief {
  constructor(public name: string, public hp: number) {}
}

class ServiceLocator {
  static get mage(): Mage {
    return Mage.instance;
  }

  static readonly thief = new Thief("Picflouz", 100);
}

console.log(ServiceLocator.mage);
console.log(ServiceLocator.thief);

Fabrique (Factory) et Monteur (Builder)

  • Une fabrique est une fonction qui génère des instances d'une classe via une fonction.
  • Un monteur est similaire à la fabrique avec la différence que les paramètres sont initialisés sous forme d'une série d'appels.
    • 💡 La technique du chaînage d'appels est souvent utilisée en complément.
  • Ces techniques permettent de substituer l'implémentation sans avoir à changer le code qui demande une instance.
  • Elle permettent aussi de proposer une syntaxe plus concise pour créer des objets complexes.
Fabrique et monteur
interface Transporter {
  readonly capacity: number;
}

class SpaceShip implements Transporter {
  constructor(
    readonly speed: number,
    readonly staelliteCount: number,
    readonly capacity: number,
    readonly shootPower: number
  ) {}
}

class Bus implements Transporter {
  constructor(readonly capacity: number) {}
}

// Fabrique (ou Factory)
function createTransporter(capacity: number): Transporter {
  return new Bus(capacity);
  //return new SpaceShip(10, 1, 4, 2200);
}

const transporter = createTransporter(2);
console.log(transporter);

// Monteur (ou Builder)
class TransporterBuilder {
  private capacity = 0;
  constructor() {}
  setCapacity(capacity: number) {
    this.capacity = capacity;
    // retourner this permet d'autoriser le chainage
    return this;
  }

  build(): Transporter {
    return new Bus(this.capacity);
  }
}

const transporter2 = new TransporterBuilder().setCapacity(5).build();
console.log(transporter2);

Exercices

Exo 1

On souhaite modéliser un garage qui répare des véhicules. Un véhicule est identifié par son matricule et a un état isBroken de type booléen.

Il n'y qu'une instance de garage possible. Le garage est identifié par son nom et permet de réparer un véhicule en basculant l'état isBroken à false. Un véhicule réparé reste en garage tant que son propriétaire n'e l'a pas récupéré. Si un véhicule n'est pas en panne, il est immédiatement remis à son propriétaire.

Un propriétaire est identifié par son nom et la listes des véhicules qu'il possède. Le propriétaire ne peut pas récupérer un véhicule qu'il ne possède pas.

Exo 2

Faire l'exercice 5.2 ce cette série avec les différences suivants:

  • Utiliser TypeScript au lieu de Java
  • Définir des factory (monteurs) pour instancier les différents enseignants (createResearcherLecturer(), etc.)