Quelle est la façon la plus simple / la plus propre d'implémenter un modèle singleton en JavaScript?
javascript
function
design-patterns
singleton
Jakub Arnold
la source
la source
Réponses:
Je pense que la façon la plus simple est de déclarer un objet littéral simple:
Si vous voulez des membres privés sur votre instance singleton, vous pouvez faire quelque chose comme ceci:
Cela a été appelé le modèle de module , il vous permet essentiellement d'encapsuler des membres privés sur un objet, en tirant parti de l'utilisation de fermetures .
MISE À JOUR: Je voudrais ajouter que si vous voulez empêcher la modification de l'objet singleton, vous pouvez le geler , en utilisant la
Object.freeze
méthode ES5 .Cela rendra l'objet immuable, empêchant toute modification de sa structure et de ses valeurs.
De plus, je voudrais mentionner que si vous utilisez ES6, vous pouvez représenter un singleton à l'aide de modules ES très facilement, et vous pouvez même conserver un état privé en déclarant des variables à la portée du module :
Ensuite, vous pouvez simplement importer l'objet singleton pour l'utiliser:
la source
publicMethod1
appellerait-onpublicMethod2
?getInstance
méthode statique et un constructeur privé-, mais IMO, c'est la façon la plus "simple" de construire un objet singleton en Javascript, et à la fin il répond au même but -un seul objet, que vous ne pouvez pas initialiser à nouveau (il n'y a pas de constructeur, c'est juste un objet) -. A propos du code lié, il a quelques problèmes, échanger lesa
etb
déclarations de variables et essaia === window
. À votre santé.Je pense que l'approche la plus propre est quelque chose comme:
Ensuite, vous pouvez appeler la fonction comme
la source
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Je ne suis pas sûr d'être d'accord avec le modèle de module utilisé en remplacement d'un modèle singleton. J'ai souvent vu des singletons utilisés et abusés dans des endroits où ils sont totalement inutiles, et je suis sûr que le modèle de module comble de nombreuses lacunes où les programmeurs utiliseraient autrement un singleton, mais le modèle de module n'est pas un singleton.
modèle de module:
Tout initialisé dans le modèle de module se produit lorsque
Foo
est déclaré. De plus, le modèle de module peut être utilisé pour initialiser un constructeur, qui pourrait ensuite être instancié plusieurs fois. Bien que le modèle de module soit le bon outil pour de nombreux travaux, il n'est pas équivalent à un singleton.motif singleton:
forme courte forme longue, en utilisant le modèle de moduleDans les deux versions du modèle Singleton que j'ai fournies, le constructeur lui-même peut être utilisé comme accesseur:
Si vous ne vous sentez pas à l'aise d'utiliser le constructeur de cette façon, vous pouvez lancer une erreur dans l'
if (instance)
instruction et vous en tenir au formulaire long:Je dois également mentionner que le modèle singleton correspond bien au modèle de fonction constructeur implicite:
la source
var singleton = {}
ne correspond pas à cette définition.var singleton = {}
est la façon dont vous implémentez singleton en Javascript .Dans
es6
:la source
instance
champ. Comme elle est actuellement (instance
définie surthis
), cette classe peut également avoir d'autres champs et le gel n'a pas de sens imo.Les travaux suivants dans le nœud v6
Nous testons:
la source
Dans ES6, la bonne façon de procéder est:
Ou, si vous ne voulez pas qu'une erreur soit levée lors de la création de la deuxième instance, vous pouvez simplement renvoyer la dernière instance, comme ceci:
la source
instance
et_instance
. C'est juste une convention de dénomination dans les langages de programmation que nous nommons les variables privées précédées d'un trait de soulignement. Je soupçonne que la raison pour laquelle votre code ne fonctionne pas est que vous utilisezthis.instance
au lieu deMyClass.instance
Il existe plusieurs façons de dépouiller un chat :) Selon votre goût ou vos besoins spécifiques, vous pouvez appliquer l'une des solutions proposées. Personnellement, je choisis la première solution de CMS chaque fois que cela est possible (lorsque vous n'avez pas besoin de confidentialité). Étant donné que la question portait sur le plus simple et le plus propre, c'est le gagnant. Ou même:
Ceci (citation de mon blog) ...
n'a pas beaucoup de sens (mon exemple de blog non plus) car il n'a pas besoin de vars privés, c'est donc à peu près la même chose que:
la source
this.f(){}
Je déconseille ma réponse, voir mon autre .
Habituellement, le modèle de module (voir la réponse de CMS) qui n'est PAS un modèle singleton est assez bon. Cependant, l'une des caractéristiques de singleton est que son initialisation est retardée jusqu'à ce que l'objet soit nécessaire. Le modèle de module n'a pas cette fonction.
Ma proposition (CoffeeScript):
Qui a compilé cela en JavaScript:
Ensuite, je peux faire ce qui suit:
la source
Réponse courte:
Du fait de la nature non bloquante de JavaScript, les singletons en JavaScript sont vraiment laids à utiliser. Les variables globales vous donneront également une instance dans toute l'application sans tous ces rappels, le modèle de module cache doucement les internes derrière l'interface. Voir la réponse @CMS.
Mais comme tu voulais un singleton…
Usage:
Explication:
Les singletons vous offrent plus d'une instance dans toute l'application: leur initialisation est retardée jusqu'à la première utilisation. C'est vraiment très important lorsque vous traitez des objets dont l'initialisation est coûteuse. Cher signifie généralement des E / S et en JavaScript, les E / S signifient toujours des rappels.
Ne vous fiez pas aux réponses qui vous donnent une interface comme
instance = singleton.getInstance()
, elles manquent toutes le point.S'ils ne prennent pas le rappel pour être exécuté lorsque l'instance est prête, ils ne fonctionneront pas lorsque l'initialiseur effectue des E / S.
Oui, les rappels semblent toujours plus laids que l'appel de fonction qui renvoie immédiatement une instance d'objet. Mais encore une fois: lorsque vous effectuez des E / S, les rappels sont obligatoires. Si vous ne voulez pas faire d'E / S, l'instanciation est assez bon marché pour le faire au démarrage du programme.
Exemple 1, initialiseur bon marché:
Exemple 2, initialisation avec E / S:
Dans cet exemple,
setTimeout
simule une opération d'E / S coûteuse. Cela illustre pourquoi les singletons en JavaScript ont vraiment besoin de rappels.la source
J'ai obtenu cet exemple de JavaScript Patterns Build Better Applications with Coding and Design Patterns par le livre de Stoyan Stefanov au cas où vous auriez besoin d'une classe d'implémentation simple comme un objet singltone, vous pouvez utiliser la fonction immédiate comme suit:
Et vous pouvez vérifier cet exemple en suivant le cas de test:
Cette approche réussit tous les cas de test tandis que l'implémentation statique privée échouera lorsque l'extension du prototype est utilisée (elle peut être corrigée mais ce ne sera pas simple) et l'implémentation statique publique moins recommandée en raison de l'instance est exposée au public.
Démo jsFiddly.
la source
Je pense avoir trouvé le moyen le plus propre de programmer en JavaScript, mais vous aurez besoin d'un peu d'imagination. J'ai eu cette idée d'une technique de travail dans le livre "javascript les bonnes pièces".
Au lieu d'utiliser le nouveau mot clé, vous pouvez créer une classe comme celle-ci:
Vous pouvez instancier l'objet ci-dessus en disant:
Maintenant, avec cette méthode de travail à l'esprit, vous pouvez créer un singleton comme celui-ci:
Vous pouvez maintenant obtenir votre instance en appelant
Je pense que c'est la meilleure façon car la "Classe" complète n'est même pas accessible.
la source
@CMS et @zzzzBov ont tous deux donné de merveilleuses réponses, mais juste pour ajouter ma propre interprétation basée sur mon passage au développement node.js lourd à partir de PHP / Zend Framework où les modèles singleton étaient courants.
Le code suivant, documenté par les commentaires, est basé sur les exigences suivantes:
Mon code est très similaire à celui de @ zzzzBov, sauf que j'ai ajouté une chaîne de prototype au constructeur et plus de commentaires qui devraient aider ceux qui viennent de PHP ou d'un langage similaire à traduire la POO traditionnelle en nature prototypique Javascripts. Ce n'est peut-être pas le "plus simple" mais je pense que c'est le plus approprié.
Notez que techniquement, la fonction anonyme auto-exécutable est elle-même un Singleton, comme le montre bien le code fourni par @CMS. Le seul hic ici, c'est qu'il n'est pas possible de modifier la chaîne prototype du constructeur lorsque le constructeur lui-même est anonyme.
Gardez à l'esprit que pour Javascript, les concepts de «public» et de «privé» ne s'appliquent pas comme ils le font en PHP ou Java. Mais nous avons obtenu le même effet en tirant parti des règles de Javascript sur la disponibilité de l'étendue fonctionnelle.
la source
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Je ne sais pas pourquoi personne n'a soulevé cette question, mais vous pouvez simplement faire:
la source
La réponse la plus claire devrait être celle-ci tirée du livre Learning JavaScript Design Patterns par Addy Osmani.
la source
Je pense que c'est la manière la plus simple / la plus propre et la plus intuitive, bien qu'elle nécessite ES7:
Le code source provient de: adam-bien.com
la source
new Singleton()
Quel est le problème avec ça?
la source
Test = Klass; t1 = new Test(); t2 = new Test();
- aucune possibilité de renommer la classe ou de choisir un espace de noms différent.puis-je mettre mes 5 pièces. J'ai une fonction constructeur, ex.
Ce que je dois faire, c'est que chaque objet créé par ce CF sera le même.
tester
la source
J'ai trouvé ce qui suit pour être le modèle Singleton plus facile, car en utilisant le nouvel opérateur rend ce immédiatement disponible au sein de la fonction, ce qui élimine la nécessité de retourner un littéral d'objet:
la source
Voici un exemple simple pour expliquer le motif singleton en javascript.
la source
J'avais besoin de plusieurs singletons avec:
et c'est donc ce que j'ai trouvé:
args doit être Array pour que cela fonctionne, donc si vous avez des variables vides, passez simplement []
J'ai utilisé un objet fenêtre dans la fonction mais j'aurais pu passer un paramètre pour créer ma propre portée
Les paramètres de nom et de construction ne sont que des chaînes de caractères pour que la fenêtre [] fonctionne, mais avec une simple vérification de type, window.name et window.construct sont également possibles.
la source
Que diriez-vous de cette façon, assurez-vous simplement que la classe ne peut pas nouveau.
Par cela, vous pouvez utiliser l'
instanceof
op, vous pouvez également utiliser la chaîne de prototype pour hériter de la classe, c'est une classe régulière, mais ne pouvez pas la créer si vous voulez obtenir l'instance, utilisez simplementgetInstance
Si vous ne voulez pas exposer le
instance
membre, mettez-le simplement dans une fermeture.la source
Voici l'extrait de ma présentation pour implémenter un modèle singleton. Cela m'est venu à l'esprit lors d'un processus d'entrevue et j'ai senti que je devrais saisir cela quelque part.
le même peut être trouvé sur ma page essentielle
la source
la source
N'est-ce pas aussi un singleton?
la source
Vous pouvez le faire avec des décorateurs comme dans cet exemple ci-dessous pour TypeScript:
Ensuite, vous utilisez votre singleton comme ceci:
À ce jour, les décorateurs ne sont pas facilement disponibles dans les moteurs JavaScript. Vous devez vous assurer que votre runtime JavaScript a réellement des décorateurs activés ou utiliser des compilateurs comme Babel et TypeScript.
Notez également que l'instance singleton est créée "paresseuse", c'est-à-dire qu'elle n'est créée que lorsque vous l'utilisez pour la première fois.
la source
Modèle de module: dans "un style plus lisible". Vous pouvez voir facilement quelles méthodes sont publiques et lesquelles sont privées
vous pouvez maintenant utiliser des méthodes publiques comme
module.method2 (); // -> J'appelle une méthode privée sur une alerte de méthode publique ("hi im a private method")
http://jsfiddle.net/ncubica/xMwS9/
la source
Singleton:
Assurez-vous qu'une classe ne possède qu'une seule instance et fournissez un point d'accès global à celle-ci.
Le modèle Singleton limite le nombre d'instances d'un objet particulier à une seule. Cette instance unique est appelée le singleton.
L'objet Singleton est implémenté comme une fonction anonyme immédiate. La fonction s'exécute immédiatement en l'enveloppant entre crochets suivi de deux crochets supplémentaires. Il est appelé anonyme car il n'a pas de nom.
Exemple de programme,
la source
Le plus simple / le plus propre pour moi signifie aussi simplement comprendre et pas de cloches et de sifflets comme on en discute beaucoup dans la version Java de la discussion:
Quel est un moyen efficace d'implémenter un modèle singleton en Java?
La réponse qui conviendrait le mieux à ce point de vue est la plus simple / la plus propre:
https://stackoverflow.com/a/70824/1497139
Et il ne peut être traduit qu'en partie en JavaScript. Certaines des différences dans Javascript sont:
Mais étant donné la dernière syntaxe ECMA, il est possible de se rapprocher avec:
Modèle singleton comme exemple de classe JavaScript
Exemple d'utilisation
Exemple de résultat
la source
Si vous êtes en cours:
Tester:
la source
Si vous souhaitez utiliser des classes:
La sortie pour ce qui précède sera:
Une autre façon d'écrire Singleton en utilisant la fonction
La sortie pour ce qui précède sera:
la source