En programmation, on connait bien le pattern Singleton où une restriction autorise l'utilisation d'une seule instance de la classe. Mais comment l'implémenter en JavaScript ?
L'objectif d'un singleton, c'est de ne pas pouvoir instancier la classe, ce qui nous permettrait d'avoir différentes copies. C'est pourquoi on demandera à l'objet de nous retourner l'instance unique à utiliser, et ce, sans utiliser la notation "new". L'utilisation de ce pattern est justifié par le fait que deux objets du même type ne devraient pas coexister dans l'application. Un autre exemple se trouve dans un système d'exploitation, où plusieurs logiciels roulent comme des singletons : on s'assure que le processus est lancé une seule fois.
Ici, je ferai en sorte d'obtenir un objet de configuration unique pour mon application web. Ainsi, on veut restreindre le programmeur à faire ceci :
// erreur!Voici un gabarit de base en JavaScript pour implémenter un singleton.
var obj = new AppConfiguration();
function AppConfiguration() {Dans le constructeur, c'est là que la magie s'opère. On vérifie la propriété caller qui retourne une référence à la fonction qui a appelé la fonction courante. Autrement dit, on retourne un objet seulement et seulement si ça a été demandé par la méthode getInstance.
// quelques propriétés
this.language = 'fr';
this.currency = 'CAD';
this.currencySymbol = '$';
this.dateFormat = 'yyyy-mm-dd';
if ( AppConfiguration.caller != AppConfiguration.getInstance ) {
throw new Error("This object cannot be instanciated");
}
}
// propriété statique qui contient l'instance unique
AppConfiguration.instance = null;
AppConfiguration.getInstance = function() {
if (this.instance == null) {
this.instance = new AppConfiguration();
}
return this.instance;
}
Bien sûr, on peut appeler plusieurs fois getInstance() mais les propriétés de l'objet seront les mêmes pour les deux "objets" puisqu'en réalité, il s'agit du même comme le démontre le test ci-dessous :
var obj1 = AppConfiguration.getInstance();Au final, même si l'objet est référencé par deux variables, elles pointent vers la même instance. Changer la propriété à une ou l'autre des variables se répercutera à l'objet unique.
// valeur par défaut: fr
console.log(obj1.language);
// changer la langue pour anglais
obj1.language = 'en';
// récupérer l'instance dans une autre variable
var obj2 = AppConfiguration.getInstance();
// la propriété language de obj2 vaut "en"!
console.log(obj2.language);
// changer la langue du 2ème objet
obj2.language = 'klingon';
// klingon
console.log(obj1.language);
// klingon
console.log(obj2.language);
Bonsoir, le pb de ton singleton est que ton instance est publique, et par conséquent modifiable. Une autre manière de créer un sigleton est la manière suivante:
module = (function(){
// att privée
var toto ;
// fonction privée
function pipi(){
...
}
// constructeur
function constructor(){
toto = 'coucou';
};
return {
// att public
att:true,
// methode public
get : function(){
return toto;}
};
})();
Tu as raison, c'est un bon truc. Mais je n'arrive toujours pas à deviner le contexte des variables et de la fonction privée de ton singleton :-)
Excellent !
J'étais à la recherche d'un moyen d'utiliser un Singleton pour communiquer entre des vues Backbone.js et voilà !
Merci pour le partage d'infos