Quelle est la façon la plus simple / la plus propre d'implémenter un modèle singleton en JavaScript?
Quelle est la façon la plus simple / la plus propre d'implémenter un modèle singleton en JavaScript?
Réponses:
Je pense que la façon la plus simple est de déclarer un objet littéral simple:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
Si vous voulez des membres privés sur votre instance singleton, vous pouvez faire quelque chose comme ceci:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accessible here
},
publicMethod2: function () {
}
};
})();
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 :
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Ensuite, vous pouvez simplement importer l'objet singleton pour l'utiliser:
import myInstance from './my-singleton.js'
// ...
publicMethod1
appellerait-on publicMethod2
?
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 les a
et b
déclarations de variables et essai a === window
. À votre santé.
Je pense que l'approche la plus propre est quelque chose comme:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Ensuite, vous pouvez appeler la fonction comme
var test = SingletonFactory.getInstance();
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.
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
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.
var Foo = function () {
"use strict";
if (Foo._instance) {
//this allows the constructor to be called multiple times
//and refer to the same instance. Another option is to
//throw an error.
return Foo._instance;
}
Foo._instance = this;
//Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
forme longue, en utilisant le modèle de module
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
//instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
Dans les deux versions du modèle Singleton que j'ai fournies, le constructeur lui-même peut être utilisé comme accesseur:
var a,
b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true
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:
var a,
b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true
Je dois également mentionner que le modèle singleton correspond bien au modèle de fonction constructeur implicite:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
//if the function wasn't called as a constructor,
//call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); //calls Foo as a constructor
-or-
var f = Foo(); //also calls Foo as a constructor
var singleton = {}
ne correspond pas à cette définition.
var singleton = {}
est la façon dont vous implémentez singleton en Javascript .
Dans es6
:
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
instance
champ. Comme elle est actuellement ( instance
définie sur this
), 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
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
Nous testons:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
Dans ES6, la bonne façon de procéder est:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
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:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // logs "true"
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 utilisez this.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:
var myInstance = {}; // done!
Ceci (citation de mon blog) ...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
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:
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
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):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Qui a compilé cela en JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Ensuite, je peux faire ce qui suit:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
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…
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Usage:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// calling instanceReady notifies singleton that instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// get instance and use it
s(function(instance) {
instance.doSomething();
});
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.
var simpleInitializer = function(instanceReady) {
console.log("Initializer started");
instanceReady({property: "initial value"});
}
var simple = singleton(simpleInitializer);
console.log("Tests started. Singleton instance should not be initalized yet.");
simple(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
simple(function(inst) {
console.log("Access 2");
console.log("Current property value: " + inst.property);
});
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.
var heavyInitializer = function(instanceReady) {
console.log("Initializer started");
var onTimeout = function() {
console.log("Initializer did his heavy work");
instanceReady({property: "initial value"});
};
setTimeout(onTimeout, 500);
};
var heavy = singleton(heavyInitializer);
console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");
heavy(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
heavy(function(inst) {
console.log("Access 2. You can see callbacks order is preserved.");
console.log("Current property value: " + inst.property);
});
console.log("We made it to the end of the file. Instance is not ready yet.");
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:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
//If private instance variable already initialized return reference
if(instance) {
return instance;
}
//If instance does not created save pointer of original reference
//to private instance variable.
instance = this;
//All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
//Some action here
};
};
}());
Et vous pouvez vérifier cet exemple en suivant le cas de test:
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
//Testing does this two object pointing to same instance
console.log(obj_1 === obj_2); //Result is true, it points to same instance object
//All prototype properites work
//no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); //Result true
//Values of properties which is defined inside of constructor
console.log(obj_1.someProperty);// output 0
console.log(obj_2.someProperty);// output 0
//Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty);// output 1
console.log(obj_2.someProperty);// output 1
console.log(obj_1.constructor === ClassName); //Output true
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.
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:
function Class()
{
var obj = {}; // Could also be used for inheritence if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod= publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
Vous pouvez instancier l'objet ci-dessus en disant:
var objInst = Class(); // !!! NO NEW KEYWORD
Maintenant, avec cette méthode de travail à l'esprit, vous pouvez créer un singleton comme celui-ci:
ClassSingleton = function()
{
var instance= null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no new keyword;
return instance;
}
return { getInstance : getInstance };
}();
Vous pouvez maintenant obtenir votre instance en appelant
var obj = ClassSingleton.getInstance();
Je pense que c'est la meilleure façon car la "Classe" complète n'est même pas accessible.
@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é.
// declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be availble in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // this should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // self execute
// ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // also returns "first" because it's the same instance as 'a'
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.
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:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// whatever
}
})()
La réponse la plus claire devrait être celle-ci tirée du livre Learning JavaScript Design Patterns par Addy Osmani.
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Singleton
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
var privateVariable = "Im also private";
var privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
Je pense que c'est la manière la plus simple / la plus propre et la plus intuitive, bien qu'elle nécessite ES7:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
Le code source provient de: adam-bien.com
new Singleton()
puis-je mettre mes 5 pièces. J'ai une fonction constructeur, ex.
var A = function(arg1){
this.arg1 = arg1
};
Ce que je dois faire, c'est que chaque objet créé par ce CF sera le même.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
tester
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
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:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Voici un exemple simple pour expliquer le motif singleton en javascript.
var Singleton=(function(){
var instance;
var init=function(){
return {
display:function(){
alert("This is a Singleton patern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance=init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a Singleton patern demo");
// It means one object is created
var inst=Singleton.getInstance();
inst.display();
// In this call only display alert("This is a Singleton patern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1=Singleton.getInstance();
inst1.display();
J'avais besoin de plusieurs singletons avec:
et c'est donc ce que j'ai trouvé:
createSingleton ('a', 'add', [1, 2]);
console.log(a);
function createSingleton (name, construct, args) {
window[name] = {};
window[construct].apply(window[name], args);
window[construct] = null;
}
function add (a, b) {
this.a = a;
this.b = b;
this.sum = a + b;
}
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.
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
function CA()
{
if(CA.instance)
{
throw new Error('can not new this class');
}else{
CA.instance = this;
}
}
/**
* @protected
* @static
* @type {CA}
*/
CA.instance = null;
/** @static */
CA.getInstance = function()
{
return CA.instance;
}
CA.prototype =
/** @lends CA#*/
{
func: function(){console.log('the func');}
}
// initilize the instance
new CA();
// test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)
// this will failed
var b = new CA();
Si vous ne voulez pas exposer le instance
membre, mettez-le simplement dans une fermeture.
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.
/*************************************************
* SINGLETON PATTERN IMPLEMENTATION *
*************************************************/
//since there are no classes in javascript, every object is technically a singleton
//if you don't inherit from it or copy from it.
var single = {};
//Singleton Implementations
//Declaring as a Global Object...you are being judged!
var Logger = function() {
//global_log is/will be defined in GLOBAL scope here
if(typeof global_log === 'undefined'){
global_log = this;
}
return global_log;
};
//the below 'fix' solves the GLOABL variable problem but
//the log_instance is publicly available and thus can be
//tampered with.
function Logger() {
if(typeof Logger.log_instance === 'undefined'){
Logger.log_instance = this;
}
return Logger.log_instance;
};
//the correct way to do it to give it a closure!
function logFactory() {
var log_instance; //private instance
var _initLog = function() { //private init method
log_instance = 'initialized';
console.log("logger initialized!")
}
return {
getLog : function(){ //the 'privileged' method
if(typeof log_instance === 'undefined'){
_initLog();
}
return log_instance;
}
};
}
/***** TEST CODE ************************************************
//using the Logger singleton
var logger = logFactory();//did i just gave LogFactory a closure?
//create an instance of the logger
var a = logger.getLog();
//do some work
//get another instance of the logger
var b = logger.getLog();
//check if the two logger instances are same?
console.log(a === b); //true
*******************************************************************/
le même peut être trouvé sur ma page essentielle
function Unicode()
{
var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
//Loop through code points
while (i < max) {
//Convert decimal to hex value, find the character, then pad zeroes to the codepoint
unicode[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
i = i + 1;
}
//Replace this function with the resulting lookup table
Unicode = unicode;
}
//Usage
Unicode();
//Lookup
Unicode["%"]; //returns 0025
Vous pouvez le faire avec des décorateurs comme dans cet exemple ci-dessous pour TypeScript:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
Ensuite, vous utilisez votre singleton comme ceci:
var myInstance = YourClass.singleton();
À 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.
Modèle de module: dans "un style plus lisible". Vous pouvez voir facilement quelles méthodes sont publiques et lesquelles sont privées
var module = (function(_name){
/*Local Methods & Values*/
var _local = {
name : _name,
flags : {
init : false
}
}
function init(){
_local.flags.init = true;
}
function imaprivatemethod(){
alert("hi im a private method");
}
/*Public Methods & variables*/
var $r = {}; //this object will hold all public methods.
$r.methdo1 = function(){
console.log("method1 call it");
}
$r.method2 = function(){
imaprivatemethod(); //calling private method
}
$r.init = function(){
inti(); //making init public in case you want to init manually and not automatically
}
init(); //automatically calling init method
return $r; //returning all publics methods
})("module");
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")
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,
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
run()
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
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Exemple d'utilisation
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Exemple de résultat
DefaultField1
DefaultField2
function Once() {
return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
let app = Once.call(this);
app.name = name;
return app;
}
Si vous êtes en cours:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Tester:
console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo
Si vous souhaitez utiliser des classes:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s',1);
let y = new Singleton('k',2);
La sortie pour ce qui précède sera:
console.log(x.name,x.age,y.name,y.age) // s 1 s 1
Une autre façon d'écrire Singleton en utilisant la fonction
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s',1);
let b = new AnotherSingleton('k',2);
La sortie pour ce qui précède sera:
console.log(a.name,a.age,b.name,b.age)// s 1 s 1