Il existe des cas où l’on souhaite exécuter un traitement d’initialisation lourd uniquement lors du premier accès, puis réutiliser la valeur générée par la suite. Ce pattern permet de l’implémenter simplement, sans la lourdeur d’un cache mémoire.
Code
export interface Reusable<T> { value: T;}
export function reusable<T>(init: () => T): Reusable<T> { return { get value() { const value = init(); Object.defineProperty(this, "value", { value }); return value; }, };}Exemples d’utilisation
Horodatage fixe
const timestamp = reusable(() => new Date());
// Date est générée lors du premier accèsconsole.log(timestamp.value); // 2025-01-18T09:00:00.000Z
// La même valeur est retournée lors des accès suivantsconsole.log(timestamp.value); // 2025-01-18T09:00:00.000ZChargement de configuration lourd
const config = reusable(() => { // Lecture de fichier, analyse de variables d'environnement, etc. return loadConfigFromFile();});
// La configuration est chargée uniquement quand nécessairefunction processData() { const settings = config.value; // Le chargement s'exécute uniquement lors du premier accès // ...}Fonctionnement de l’implémentation
- Exécute la fonction init lors du premier accès au getter
- Remplace value par une propriété de données en utilisant Object.defineProperty
- Lors des accès suivants, le getter n’est pas appelé et la valeur est retournée directement
Ainsi, le coût d’initialisation ne se produit que lors du premier accès, et les accès suivants offrent des performances équivalentes à l’accès à une propriété normale.
Comparaison avec le cache mémoire
Différences avec les caches mémoire (comme Map) :
- Ce pattern est spécialisé pour les valeurs uniques
- Pas besoin de gestion de clés comme avec Map
- Le garbage collection se comporte comme pour les objets ordinaires
Inversement, utilisez Map ou WeakMap lorsque vous souhaitez mettre en cache plusieurs valeurs.
Points d’attention
Une fois initialisée, la valeur ne change jamais. Pour réinitialiser, vous devez créer une nouvelle instance reusable. De plus, si la fonction init lève une exception, la même exception sera relancée lors des accès suivants.
hsb.horse