Qual è il modo più semplice / pulito per implementare il modello singleton in JavaScript?
Qual è il modo più semplice / pulito per implementare il modello singleton in JavaScript?
Risposte:
Penso che il modo più semplice sia dichiarare un semplice oggetto letterale:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
Se vuoi membri privati nella tua istanza singleton, puoi fare qualcosa del genere:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accessible here
},
publicMethod2: function () {
}
};
})();
Questo è stato chiamato il modello del modulo , in pratica consente di incapsulare membri privati su un oggetto, sfruttando l'utilizzo di chiusure .
AGGIORNAMENTO: Vorrei aggiungere che se si desidera impedire la modifica dell'oggetto singleton, è possibile bloccarlo utilizzando ES5Object.freeze
metodo .
Ciò renderà l'oggetto immutabile, impedendo qualsiasi modifica alla sua struttura e ai suoi valori.
Inoltre, vorrei menzionare che se si utilizza ES6, è possibile rappresentare un singleton utilizzando i moduli ES molto facilmente e si può persino mantenere lo stato privato dichiarando le variabili nell'ambito del modulo :
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Quindi puoi semplicemente importare l'oggetto singleton per usarlo:
import myInstance from './my-singleton.js'
// ...
publicMethod1
chiamerebbe publicMethod2
?
getInstance
metodo statico e un costrutto privato-, ma IMO, questo è il modo più "semplice" per costruire un oggetto singleton in Javascript, e alla fine soddisfa lo stesso scopo -un singolo oggetto, che non puoi inizializzare di nuovo (non c'è un costruttore, è solo un oggetto) -. Circa il codice si è collegato, ha alcuni problemi, scambiare le a
e b
variabili dichiarazioni e di prova a === window
. Saluti.
Penso che l'approccio più pulito sia qualcosa di simile:
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;
}
};
})();
Successivamente, è possibile richiamare la funzione come
var test = SingletonFactory.getInstance();
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Non sono sicuro di essere d'accordo con il modello di modulo utilizzato in sostituzione di un modello singleton. Ho visto spesso i singleton usati e maltrattati in luoghi in cui sono del tutto superflui, e sono sicuro che il pattern del modulo colma molte lacune in cui i programmatori userebbero un singleton, tuttavia il pattern del modulo non è un singleton.
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Tutto ciò che è inizializzato nel modello del modulo accade quando Foo
viene dichiarato. Inoltre, il modello di modulo può essere utilizzato per inizializzare un costruttore, che può quindi essere istanziato più volte. Mentre il modello del modulo è lo strumento giusto per molti lavori, non è equivalente a 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();
}
forma lunga, usando il modello del modulo
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;
}());
In entrambe le versioni del modello Singleton che ho fornito, il costruttore stesso può essere utilizzato come accessorio:
var a,
b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true
Se non ti senti a tuo agio nell'usare il costruttore in questo modo, puoi lanciare un errore if (instance)
nell'istruzione e continuare ad usare la forma lunga:
var a,
b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true
Dovrei anche menzionare che il modello singleton si adatta bene al modello di funzione del costruttore implicito:
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 = {}
non corrisponde a tale definizione.
var singleton = {}
è come si implementa singleton in Javascript .
In 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
campo. Come è attualmente ( instance
impostato su this
) questa classe potrebbe avere anche altri campi e il congelamento non ha senso imo.
Quanto segue funziona nel nodo v6
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
Testiamo:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
In ES6 il modo giusto per farlo è:
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
Oppure, se non desideri che venga generato un errore durante la creazione della seconda istanza, puoi semplicemente restituire l'ultima istanza, in questo modo:
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
e _instance
. È solo una convenzione di denominazione nei linguaggi di programmazione che chiamiamo variabili private precedute da un trattino basso. Sospetto che il motivo per cui il tuo codice non funziona è che stai utilizzando this.instance
invece diMyClass.instance
Esistono più modi per scuoiare un gatto :) A seconda dei tuoi gusti o delle tue esigenze specifiche puoi applicare una qualsiasi delle soluzioni proposte. Personalmente cerco la prima soluzione di CMS ogni volta che è possibile (quando non hai bisogno di privacy). Poiché la domanda riguardava il più semplice e il più pulito, quello è il vincitore. O anche:
var myInstance = {}; // done!
Questo (citazione dal mio blog) ...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
non ha molto senso (il mio esempio di blog non lo fa neanche) perché non ha bisogno di alcun parametro privato, quindi è praticamente lo stesso di:
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
this.f(){}
Deprezzo la mia risposta, vedi la mia altra .
Di solito il modello di modulo (vedi la risposta di CMS) che NON è un modello singleton è abbastanza buono. Tuttavia una delle caratteristiche di singleton è che la sua inizializzazione è ritardata fino a quando non è necessario l'oggetto. Il modello del modulo non ha questa funzione.
La mia proposta (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Che ha compilato questo in JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Quindi posso fare quanto segue:
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
A causa della natura non bloccante di JavaScript, i Singleton in JavaScript sono davvero brutti in uso. Le variabili globali ti daranno un'istanza anche attraverso l'intera applicazione senza tutti questi callback, il modello di modulo nasconde delicatamente gli interni dietro l'interfaccia. Vedi la risposta di @CMS.
Ma, dal momento che volevi 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);
}
};
};
Uso:
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();
});
I singleton offrono più di una sola istanza nell'intera applicazione: la loro inizializzazione è ritardata fino al primo utilizzo. Questa è davvero una grande cosa quando si tratta di oggetti la cui inizializzazione è costosa. Costoso di solito significa I / O e in JavaScript I / O significa sempre richiamate.
Non fidarti delle risposte che ti danno un'interfaccia simile instance = singleton.getInstance()
, tutti mancano il punto.
Se non accettano l'esecuzione del callback quando l'istanza è pronta, non funzioneranno quando l'inizializzatore esegue l'I / O.
Sì, i callback sembrano sempre più brutti della chiamata di funzione che restituisce immediatamente l'istanza dell'oggetto. Ma ancora: quando si esegue l'I / O, i callback sono obbligatori. Se non si desidera eseguire alcun I / O, l'istanza è abbastanza economica per farlo all'avvio del programma.
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);
});
In questo esempio viene setTimeout
eseguita un'operazione I / O costosa. Questo spiega perché i singoli in JavaScript hanno davvero bisogno di callback.
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.");
Ho preso questo esempio da JavaScript Patterns Build Better Applications with Coding and Design Patterns Dal libro di Stoyan Stefanov nel caso in cui abbiate bisogno di una semplice classe di implementazione come l'oggetto singltone, potete usare la funzione immediata come segue:
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
};
};
}());
E puoi controllare questo esempio seguendo il test case:
//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
Questo approccio supera tutti i casi di test mentre l'implementazione statica privata fallirà quando viene utilizzata l'estensione del prototipo (può essere riparata ma non sarà semplice) e l'implementazione statica pubblica meno consigliabile a causa dell'istanza è esposta al pubblico.
Penso di aver trovato il modo più pulito per programmare in JavaScript, ma avrai bisogno di un po 'di immaginazione. Ho avuto questa idea da una tecnica di lavoro nel libro "javascript the good parts".
Invece di utilizzare la nuova parola chiave, è possibile creare una classe come questa:
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;
}
È possibile creare un'istanza dell'oggetto sopra dicendo:
var objInst = Class(); // !!! NO NEW KEYWORD
Ora con questo metodo di lavoro in mente potresti creare un singleton come questo:
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 };
}();
Ora puoi ottenere la tua istanza chiamando
var obj = ClassSingleton.getInstance();
Penso che questo sia il modo più accurato in quanto la "Classe" completa non è nemmeno accessibile.
@CMS e @zzzzBov hanno dato entrambe risposte meravigliose, ma solo per aggiungere la mia interpretazione basata sul fatto che mi sono trasferito nello sviluppo di node.js pesante da PHP / Zend Framework in cui i modelli singleton erano comuni.
Il seguente codice documentato da commenti si basa sui seguenti requisiti:
Il mio codice è molto simile a quello di @ zzzzBov, tranne per il fatto che ho aggiunto una catena di prototipi al costruttore e altri commenti che dovrebbero aiutare coloro che provengono da PHP o un linguaggio simile a tradurre OOP tradizionale in natura prototipica di Javascripts. Potrebbe non essere il "più semplice" ma credo che sia il più corretto.
// 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'
Si noti che tecnicamente, la funzione anonima autoeseguente è essa stessa un Singleton, come ben dimostrato nel codice fornito da @CMS. L'unico problema è che non è possibile modificare la catena di prototipi del costruttore quando il costruttore stesso è anonimo.
Tieni presente che per Javascript, i concetti di "pubblico" e "privato" non si applicano come in PHP o Java. Ma abbiamo ottenuto lo stesso effetto sfruttando le regole di Javascript relative alla disponibilità dell'ambito funzionale.
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Non sono sicuro del motivo per cui nessuno ha parlato di questo, ma potresti semplicemente fare:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// whatever
}
})()
La risposta più chiara dovrebbe essere questa dal libro Learning JavaScript Design Patterns di 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;
}
};
})();
Credo che questo sia il modo più semplice / pulito e intuitivo anche se richiede ES7:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
Il codice sorgente proviene da: adam-bien.com
new Singleton()
posso mettere le mie 5 monete. Ho una funzione di costruzione, ad es.
var A = function(arg1){
this.arg1 = arg1
};
Quello che devo fare è che ogni oggetto creato da questo CF sarà lo stesso.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
test
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Ho trovato il seguente per essere il pattern Singleton più facile, perché con il nuovo operatore rende questo immediatamente disponibili all'interno della funzione, eliminando la necessità di restituire un oggetto letterale:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Ecco il semplice esempio per spiegare il modello singleton in 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();
Avevo bisogno di diversi singoli con:
e quindi questo è quello che mi è venuto in mente:
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 deve essere Array affinché funzioni, quindi se hai variabili vuote, passa []
Ho usato l'oggetto finestra nella funzione ma avrei potuto passare un parametro per creare il mio ambito
i parametri nome e costrutto sono solo String per il funzionamento di window [] ma con alcuni semplici controlli del tipo, sono anche possibili window.name e window.construct.
Che ne dici di questo, assicurati che la classe non possa più essere nuova.
Con questo, puoi usare anche l' instanceof
op, puoi usare la catena di prototipi per ereditare la classe, è una classe normale, ma non puoi rinnovarla, se vuoi ottenere l'istanza basta usaregetInstance
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();
Se non vuoi esporre il instance
membro, mettilo in una chiusura.
Di seguito è riportato il frammento della mia passeggiata attraverso per implementare un modello singleton. Questo mi è venuto in mente durante un processo di intervista e ho sentito che avrei dovuto catturarlo da qualche parte.
/*************************************************
* 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
*******************************************************************/
lo stesso può essere trovato sul mio succo pagina
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
Puoi farlo con decoratori come nell'esempio seguente per TypeScript:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
Quindi usi il tuo singleton in questo modo:
var myInstance = YourClass.singleton();
Al momento della stesura di questo documento, i decoratori non sono prontamente disponibili nei motori JavaScript. Dovresti assicurarti che il runtime JavaScript abbia effettivamente i decoratori abilitati o utilizzare compilatori come Babel e TypeScript.
Si noti inoltre che l'istanza singleton viene creata "pigra", ovvero viene creata solo quando la si utilizza per la prima volta.
Schema del modulo: in "stile più leggibile". Puoi vedere facilmente quali metodi sono pubblici e quali sono privati
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");
ora puoi usare metodi pubblici come
module.method2 (); // -> Sto chiamando un metodo privato tramite un avviso di metodo pubblico ("ciao im un metodo privato")
Singleton:
Assicurati che una classe abbia solo un'istanza e fornisci un punto di accesso globale ad essa.
Il modello Singleton limita il numero di istanze di un particolare oggetto a una sola. Questa singola istanza è chiamata singleton.
L'oggetto Singleton è implementato come una funzione anonima immediata. La funzione viene eseguita immediatamente racchiudendola tra parentesi seguita da due parentesi aggiuntive. Si chiama anonimo perché non ha un nome.
Programma di esempio,
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()
Più semplice / più pulito per me significa anche semplicemente capire e senza campane e fischietti come sono molto discussi nella versione Java della discussione:
Qual è un modo efficiente per implementare un modello singleton in Java?
Dal mio punto di vista la risposta che si adatterebbe meglio al più semplice / pulito è:
https://stackoverflow.com/a/70824/1497139
E può essere tradotto solo parzialmente in JavaScript. Alcune delle differenze in Javascript sono:
Ma data la sintassi ECMA più recente, è possibile avvicinarsi a:
Modello Singleton come esempio di 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;
}
}
Esempio di utilizzo
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Risultato di esempio
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;
}
Se sei in classe:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Test:
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
Se vuoi usare le classi:
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);
L'output per quanto sopra sarà:
console.log(x.name,x.age,y.name,y.age) // s 1 s 1
Un altro modo di scrivere Singleton usando la funzione
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);
L'output per quanto sopra sarà:
console.log(a.name,a.age,b.name,b.age)// s 1 s 1