Was ist der einfachste / sauberste Weg, um Singleton-Muster in JavaScript zu implementieren?
Was ist der einfachste / sauberste Weg, um Singleton-Muster in JavaScript zu implementieren?
Antworten:
Ich denke, der einfachste Weg ist, ein einfaches Objektliteral zu deklarieren:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
Wenn Sie private Mitglieder in Ihrer Singleton-Instanz haben möchten, können Sie Folgendes tun:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accessible here
},
publicMethod2: function () {
}
};
})();
Dies wurde genannt das Modul Muster , es im Grunde können Sie private Mitglieder auf ein Objekt kapseln, von Vorteil bei der Verwendung der Einnahme Schließungen .
UPDATE: Ich möchte hinzufügen, dass Sie das Singleton-Objekt mithilfe der ES5- Methode einfrieren können, wenn Sie die Änderung des Singleton-Objekts verhindern möchten Object.freeze
.
Dadurch wird das Objekt unveränderlich und es werden keine Änderungen an seiner Struktur und seinen Werten vorgenommen.
Darüber hinaus möchte ich erwähnen, dass Sie mit ES6 sehr einfach einen Singleton mit ES-Modulen darstellen und sogar den privaten Status beibehalten können, indem Sie Variablen im Modulbereich deklarieren :
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Dann können Sie einfach das Singleton-Objekt importieren, um es zu verwenden:
import myInstance from './my-singleton.js'
// ...
publicMethod1
anrufen publicMethod2
?
getInstance
Methode und einen privaten Konstruktor beinhalteten -, aber IMO, dies ist der "einfachste" Weg, ein Singleton-Objekt zu erstellen in Javascript, und am Ende erfüllt es den gleichen Zweck - ein einzelnes Objekt, das Sie nicht erneut initialisieren können (es gibt keinen Konstruktor, es ist nur ein Objekt) -. Über den Code, den Sie verlinkt haben, gibt es einige Probleme, tauschen Sie die a
und b
Variablendeklarationen aus und testen Sie a === window
. Prost.
Ich denke, der sauberste Ansatz ist so etwas wie:
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;
}
};
})();
Anschließend können Sie die Funktion als aufrufen
var test = SingletonFactory.getInstance();
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Ich bin nicht sicher, ob ich mit dem Modulmuster einverstanden bin, das als Ersatz für ein Singleton-Muster verwendet wird. Ich habe oft gesehen, wie Singletons an Orten verwendet und missbraucht wurden, an denen sie völlig unnötig sind, und ich bin sicher, dass das Modulmuster viele Lücken füllt, in denen Programmierer sonst einen Singleton verwenden würden, aber das Modulmuster ist kein Singleton.
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Alles, was im Modulmuster initialisiert wurde, geschieht, wenn Foo
es deklariert wird. Zusätzlich kann das Modulmuster verwendet werden, um einen Konstruktor zu initialisieren, der dann mehrmals instanziiert werden kann. Während das Modulmuster das richtige Werkzeug für viele Jobs ist, entspricht es nicht einem 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();
}
lange Form mit Modulmuster
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 beiden Versionen des von mir bereitgestellten Singleton-Musters kann der Konstruktor selbst als Accessor verwendet werden:
var a,
b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true
Wenn Sie sich mit dem Konstruktor auf diese Weise nicht wohl fühlen, können Sie einen Fehler in die if (instance)
Anweisung werfen und sich an die lange Form halten:
var a,
b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true
Ich sollte auch erwähnen, dass das Singleton-Muster gut zum impliziten Konstruktorfunktionsmuster passt:
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 = {}
passt nicht zu dieser Definition.
var singleton = {}
So implementieren Sie 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
Feld haben würde. Da es derzeit ( instance
auf this
) gesetzt ist, kann diese Klasse auch andere Felder haben und das Einfrieren macht imo keinen Sinn.
Das Folgende funktioniert in Knoten v6
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
Wir testen:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
In ES6 ist der richtige Weg, dies zu tun:
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
Wenn Sie nicht möchten, dass bei der Erstellung der zweiten Instanz ein Fehler ausgegeben wird, können Sie einfach die letzte Instanz wie folgt zurückgeben:
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
und _instance
. Es ist nur eine Namenskonvention in Programmiersprachen, dass wir private Variablen benennen, denen ein Unterstrich vorangestellt ist. Ich vermute, der Grund dafür, dass Ihr Code nicht funktioniert, ist, dass Sie this.instance
anstelle vonMyClass.instance
Es gibt mehrere Möglichkeiten, eine Katze zu häuten :) Je nach Geschmack oder Bedarf können Sie eine der vorgeschlagenen Lösungen anwenden. Ich persönlich greife nach Möglichkeit zur ersten Lösung von CMS (wenn Sie keine Privatsphäre benötigen). Da es sich um die einfachste und sauberste Frage handelte, ist dies der Gewinner. Oder auch:
var myInstance = {}; // done!
Dies (Zitat aus meinem Blog) ...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
macht nicht viel Sinn (mein Blog-Beispiel auch nicht), weil es keine privaten Vars benötigt, also ist es so ziemlich das Gleiche wie:
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
this.f(){}
Ich lehne meine Antwort ab, siehe meine andere .
Normalerweise ist ein Modulmuster (siehe Antwort von CMS), das KEIN Singleton-Muster ist, gut genug. Eines der Merkmale von Singleton ist jedoch, dass seine Initialisierung verzögert wird, bis ein Objekt benötigt wird. Dem Modulmuster fehlt diese Funktion.
Mein Vorschlag (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Welche dazu in JavaScript kompiliert:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Dann kann ich folgendes tun:
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
Da JavaScript nicht blockierend ist, werden Singletons in JavaScript sehr hässlich verwendet. Globale Variablen geben Ihnen auch eine Instanz durch die gesamte Anwendung ohne all diese Rückrufe. Das Modulmuster verbirgt die Interna sanft hinter der Schnittstelle. Siehe @ CMS-Antwort.
Aber da Sie einen Singleton wollten ...
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);
}
};
};
Verwendungszweck:
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();
});
Singletons bieten Ihnen mehr als nur eine Instanz für die gesamte Anwendung: Ihre Initialisierung wird bis zur ersten Verwendung verzögert. Dies ist eine wirklich große Sache, wenn Sie sich mit Objekten befassen, deren Initialisierung teuer ist. Teuer bedeutet normalerweise E / A und in JavaScript bedeutet E / A immer Rückrufe.
Vertraue keinen Antworten, die dir eine Schnittstelle geben instance = singleton.getInstance()
, sie verfehlen alle den Punkt.
Wenn sie keinen Rückruf annehmen, um ausgeführt zu werden, wenn die Instanz bereit ist, funktionieren sie nicht, wenn der Initialisierer E / A ausführt.
Ja, Rückrufe sehen immer hässlicher aus als Funktionsaufrufe, die sofort eine Objektinstanz zurückgeben. Aber noch einmal: Wenn Sie E / A ausführen, sind Rückrufe obligatorisch. Wenn Sie keine E / A ausführen möchten, ist die Instanziierung billig genug, um sie beim Programmstart auszuführen.
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 diesem Beispiel wird setTimeout
eine teure E / A-Operation vorgetäuscht. Dies zeigt, warum Singletons in JavaScript wirklich Rückrufe benötigen.
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.");
Ich habe dieses Beispiel von JavaScript-Mustern erhalten. Bessere Anwendungen mit Codierungs- und Entwurfsmustern erstellen Von Stoyan Stefanovs Buch Für den Fall, dass Sie eine einfache Implementierungsklasse wie ein Singltone-Objekt benötigen, können Sie die sofortige Funktion wie folgt verwenden:
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
};
};
}());
Sie können dieses Beispiel anhand des folgenden Testfalls überprüfen:
//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
Dieser Ansatz besteht alle Testfälle, während die private statische Implementierung fehlschlägt, wenn die Prototyperweiterung verwendet wird (sie kann behoben werden, ist aber nicht einfach) und die öffentliche statische Implementierung weniger ratsam ist, da die Instanz der Öffentlichkeit zugänglich ist.
Ich glaube, ich habe den saubersten Weg gefunden, um in JavaScript zu programmieren, aber Sie brauchen etwas Fantasie. Ich habe diese Idee von einer Arbeitstechnik im Buch "Javascript the good parts" erhalten.
Anstatt das neue Schlüsselwort zu verwenden, können Sie eine Klasse wie die folgende erstellen:
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;
}
Sie können das obige Objekt instanziieren, indem Sie sagen:
var objInst = Class(); // !!! NO NEW KEYWORD
Mit dieser Arbeitsmethode können Sie nun einen Singleton wie folgt erstellen:
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 };
}();
Jetzt können Sie Ihre Instanz durch Aufrufen erhalten
var obj = ClassSingleton.getInstance();
Ich denke, dies ist der sauberste Weg, da die gesamte "Klasse" nicht einmal zugänglich ist.
@CMS und @zzzzBov haben beide wundervolle Antworten gegeben, aber nur um meine eigene Interpretation hinzuzufügen, basierend darauf, dass ich in die Entwicklung von Heavy Node.js aus PHP / Zend Framework gewechselt bin, wo Singleton-Muster üblich waren.
Der folgende, kommentarisch dokumentierte Code basiert auf den folgenden Anforderungen:
Mein Code ist dem von @ zzzzBov sehr ähnlich, außer dass ich dem Konstruktor eine Prototypenkette und weitere Kommentare hinzugefügt habe, die denjenigen helfen sollen, die aus PHP oder einer ähnlichen Sprache stammen, die traditionelle OOP in die prototypische Natur von Javascripts zu übersetzen. Es ist vielleicht nicht das "einfachste", aber ich glaube, es ist das richtigste.
// 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'
Beachten Sie, dass die selbstausführende anonyme Funktion technisch gesehen selbst ein Singleton ist, wie der von @CMS bereitgestellte Code zeigt. Der einzige Haken dabei ist, dass es nicht möglich ist, die Prototypkette des Konstruktors zu ändern, wenn der Konstruktor selbst anonym ist.
Beachten Sie, dass für Javascript die Konzepte "öffentlich" und "privat" nicht wie in PHP oder Java gelten. Wir haben jedoch den gleichen Effekt erzielt, indem wir die Regeln von Javascript zur Verfügbarkeit des Funktionsumfangs genutzt haben.
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Ich bin mir nicht sicher, warum niemand dies angesprochen hat, aber Sie können einfach Folgendes tun:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// whatever
}
})()
Die klarste Antwort sollte diese aus dem Buch Learning JavaScript Design Patterns von Addy Osmani sein.
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;
}
};
})();
Ich glaube, dies ist der einfachste / sauberste und intuitivste Weg, obwohl ES7 erforderlich ist:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
Der Quellcode stammt von: adam-bien.com
new Singleton()
kann ich meine 5 Münzen legen. Ich habe eine Konstruktorfunktion, z.
var A = function(arg1){
this.arg1 = arg1
};
Was ich tun muss, ist, dass nur jedes von dieser CF erstellte Objekt gleich ist.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
Prüfung
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Ich habe festgestellt, dass das Folgende das einfachste Singleton-Muster ist, da die Verwendung des neuen Operators dieses sofort innerhalb der Funktion verfügbar macht , sodass kein Objektliteral zurückgegeben werden muss:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Hier ist das einfache Beispiel, um das Singleton-Muster in Javascript zu erklären.
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();
Ich brauchte mehrere Singletons mit:
und so kam ich auf Folgendes:
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 muss Array sein, damit dies funktioniert. Wenn Sie leere Variablen haben, übergeben Sie einfach []
Ich habe ein Fensterobjekt in der Funktion verwendet, aber ich hätte einen Parameter übergeben können, um meinen eigenen Bereich zu erstellen
Name- und Konstruktparameter sind nur Zeichenfolgen, damit window [] funktioniert. Mit einigen einfachen Typprüfungen sind jedoch auch window.name und window.construct möglich.
Wie wäre es auf diese Weise, nur versichern, dass die Klasse nicht wieder neu sein kann.
Auf diese Weise können Sie die instanceof
Operation verwenden. Sie können auch die Prototypenkette verwenden, um die Klasse zu erben. Es handelt sich um eine reguläre Klasse, die jedoch nicht neu erstellt werden kann, wenn Sie die Instanz nur verwenden möchtengetInstance
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();
Wenn Sie das instance
Mitglied nicht aussetzen möchten , schließen Sie es einfach.
Das Folgende ist der Ausschnitt aus meinem Durchgang, um ein Singleton-Muster zu implementieren. Dies kam mir während eines Interviewprozesses in den Sinn und ich hatte das Gefühl, dass ich das irgendwo festhalten sollte.
/*************************************************
* 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
*******************************************************************/
das gleiche kann auf meiner findet Kern Seite
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
Sie können dies mit Dekoratoren wie in diesem Beispiel für TypeScript tun:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
Dann verwenden Sie Ihren Singleton wie folgt:
var myInstance = YourClass.singleton();
Zum jetzigen Zeitpunkt sind Dekoratoren in JavaScript-Engines nicht ohne weiteres verfügbar. Sie müssen sicherstellen, dass in Ihrer JavaScript-Laufzeit Dekoratoren tatsächlich aktiviert sind, oder Compiler wie Babel und TypeScript verwenden.
Beachten Sie auch, dass die Singleton-Instanz "faul" erstellt wird, dh nur, wenn Sie sie zum ersten Mal verwenden.
Modulmuster: im "besser lesbaren Stil". Sie können leicht erkennen, welche Methoden öffentlich und welche privat sind
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");
Jetzt können Sie öffentliche Methoden wie verwenden
module.method2 (); // -> Ich rufe eine private Methode über eine öffentliche Methodenwarnung auf ("hi im a private method")
Singleton:
Stellen Sie sicher, dass eine Klasse nur eine Instanz hat, und stellen Sie einen globalen Zugriffspunkt darauf bereit.
Das Singleton-Muster begrenzt die Anzahl der Instanzen eines bestimmten Objekts auf nur eine. Diese einzelne Instanz wird als Singleton bezeichnet.
Das Singleton-Objekt wird als sofortige anonyme Funktion implementiert. Die Funktion wird sofort ausgeführt, indem sie in Klammern gefolgt von zwei zusätzlichen Klammern eingeschlossen wird. Es wird anonym genannt, weil es keinen Namen hat.
Beispielprogramm,
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()
Am einfachsten / saubersten bedeutet für mich auch einfach zu verstehen und ohne Schnickschnack, wie in der Java-Version der Diskussion viel diskutiert:
Was ist ein effizienter Weg, um ein Singleton-Muster in Java zu implementieren?
Die Antwort, die aus meiner Sicht am einfachsten / saubersten dort passt, lautet:
https://stackoverflow.com/a/70824/1497139
Und es kann nur teilweise in JavaScript übersetzt werden. Einige der Unterschiede in Javascript sind:
Angesichts der neuesten ECMA-Syntax ist es jedoch möglich, Folgendes zu erreichen:
Singleton-Muster als JavaScript-Klassenbeispiel
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;
}
}
Beispiel Verwendung
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Beispiel Ergebnis
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;
}
Wenn Sie in Klassen sind:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Prüfung:
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
Wenn Sie Klassen verwenden möchten:
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);
Die Ausgabe für die oben genannten wird sein:
console.log(x.name,x.age,y.name,y.age) // s 1 s 1
Eine andere Art, Singleton mit der Funktion zu schreiben
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);
Die Ausgabe für die oben genannten wird sein:
console.log(a.name,a.age,b.name,b.age)// s 1 s 1