JavaScriptでシングルトンパターンを実装する最も簡単でクリーンな方法は何ですか?
JavaScriptでシングルトンパターンを実装する最も簡単でクリーンな方法は何ですか?
回答:
最も簡単な方法は、単純なオブジェクトリテラルを宣言することだと思います。
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
シングルトンインスタンスにプライベートメンバーが必要な場合は、次のようにすることができます。
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accessible here
},
publicMethod2: function () {
}
};
})();
これはモジュールパターンと呼ばれ、基本的に、クロージャーの使用を利用して、オブジェクトのプライベートメンバーをカプセル化できます。
更新:シングルトンオブジェクトの変更を防止したい場合は、ES5 メソッドを使用してフリーズできますObject.freeze
。
これにより、オブジェクトが不変になり、オブジェクトの構造と値が変更されなくなります。
さらに、ES6を使用している場合は、ESモジュールを使用してシングルトンを非常に簡単に表すことができ、モジュールスコープで変数を宣言することでプライベート状態を保持することもできます。
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
その後、シングルトンオブジェクトをインポートして使用できます。
import myInstance from './my-singleton.js'
// ...
publicMethod1
呼び出すpublicMethod2
でしょうか?
getInstance
私は静的メソッドとプライベートコンストラクターを含む多くの実装を覚えていますが、IMO、これはシングルトンオブジェクトを構築する最も「簡単な」方法ですJavaScriptでは、最終的には同じ目的を満たします-単一オブジェクトであり、再度初期化することはできません(コンストラクタはなく、単なるオブジェクトです)。リンクしたコードについて、いくつかの問題がa
ありb
ますa === window
。変数と変数の宣言を入れ替えてテストしてください。乾杯。
私は最もクリーンなアプローチは次のようなものだと思います:
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;
}
};
})();
その後、次のように関数を呼び出すことができます
var test = SingletonFactory.getInstance();
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
シングルトンパターンの代わりとして使用されるモジュールパターンに同意するかどうかはわかりません。完全に不要な場所でシングルトンが使用および乱用されることはよくあります。モジュールパターンがシングルトンを使用しない場合、モジュールパターンはシングルトンではありませんが、モジュールパターンが多くのギャップを埋めると確信しています。
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Foo
が宣言されると、モジュールパターンで初期化されたすべてが発生します。さらに、モジュールパターンを使用してコンストラクターを初期化できます。コンストラクターは複数回インスタンス化できます。モジュールパターンは多くのジョブに適したツールですが、シングルトンと同等ではありません。
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();
}
長い形式、モジュールパターンを使用
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;
}());
私が提供したシングルトンパターンの両方のバージョンで、コンストラクター自体をアクセサーとして使用できます。
var a,
b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true
この方法でコンストラクタを使いたくない場合は、if (instance)
ステートメントでエラーをスローし、長い形式をそのまま使用できます。
var a,
b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true
また、シングルトンパターンは、暗黙のコンストラクター関数パターンにうまく適合することにも言及する必要があります。
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 = {}
その定義に適合しません。
var singleton = {}
JavaScriptでシングルトンを実装する方法です。
で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
フィールドのみを持つ場合、フリーズは理にかなっています。現在の(にinstance
設定されているthis
)ため、このクラスには他のフィールドも含まれる可能性があり、凍結は意味がありません。
以下はノードv6で動作します
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
私たちはテストします:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
ES6では、これを行う正しい方法は次のとおりです。
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
または、2番目のインスタンスの作成時にエラーがスローされないようにするには、次のように最後のインスタンスを返すだけです。
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
ありません_instance
。アンダースコアを前に付けたプライベート変数に名前を付けるのは、プログラミング言語の命名規則にすぎません。あなたのコードが機能しない理由は、あなたがthis.instance
代わりに使用しているためだと思いますMyClass.instance
猫の皮をむく方法は複数あります:)好みや特定のニーズに応じて、提案されたソリューションのいずれかを適用できます。個人的には、可能な場合はいつでも(プライバシーが必要ない場合)CMSの最初のソリューションを採用します。質問は最もシンプルでクリーンなものだったので、それが勝者です。あるいは:
var myInstance = {}; // done!
これ(私のブログからの引用)...
var SingletonClass = new function() {
this.myFunction() {
//do stuff
}
this.instance = 1;
}
プライベート変数を必要としないため、あまり意味がありません(私のブログの例もそうではありません)。したがって、次のコードとほとんど同じです。
var SingletonClass = {
myFunction: function () {
//do stuff
},
instance: 1
}
this.f(){}
私は自分の回答を非推奨にしています。他の回答をご覧ください。
通常、シングルトンパターンではないモジュールパターン(CMSの回答を参照)で十分です。ただし、シングルトンの機能の1つは、オブジェクトが必要になるまで初期化が遅延することです。モジュールパターンにはこの機能がありません。
私の命題(CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
これはJavaScriptでこれにコンパイルされました:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
その後、私は以下を行うことができます:
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
JavaScriptの非ブロッキング性のため、JavaScriptのシングルトンは実際には醜いです。グローバル変数は、これらすべてのコールバックなしで、アプリケーション全体を通じて1つのインスタンスを提供します。モジュールパターンは、内部を内部的にインターフェイスの背後に静かに隠します。@CMSの回答を参照してください。
しかし、シングルトンが必要だったので…
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);
}
};
};
使用法:
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();
});
シングルトンは、アプリケーション全体で1つ以上のインスタンスを提供します。それらの初期化は、最初の使用まで遅延されます。初期化にコストがかかるオブジェクトを扱う場合、これは非常に重要です。高価なは通常I / Oを意味し、JavaScriptではI / Oは常にコールバックを意味します。
のようなインターフェースを提供する回答は信用しないでくださいinstance = singleton.getInstance()
。
インスタンスの準備ができているときにコールバックを実行しないと、イニシャライザがI / Oを実行しても機能しません。
ええ、コールバックは常にオブジェクトのインスタンスをすぐに返す関数呼び出しよりも醜く見えます。しかし、繰り返しになりますが、I / Oを行う場合、コールバックは必須です。I / Oを行いたくない場合、インスタンス化はプログラムの開始時にそれを行うのに十分安価です。
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);
});
この例ではsetTimeout
、高価なI / O操作を偽装しています。これは、JavaScriptのシングルトンが本当にコールバックを必要とする理由を示しています。
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.");
この例は、JavaScriptパターンから取得しました。コーディングパターンとデザインパターンを使用してより良いアプリケーションを構築するStoyan Stefanovの本によると、singltoneオブジェクトのような単純な実装クラスが必要な場合は、次のように即時関数を使用できます。
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
};
};
}());
また、次のテストケースでこの例を確認できます。
//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
このアプローチはすべてのテストケースに合格しますが、プロトタイプ拡張が使用されるとプライベート静的実装は失敗し(修正は可能ですが、簡単ではありません)、インスタンスがパブリックに公開されるためあまり推奨されないパブリック静的実装です。
私はJavaScriptでプログラムする最もクリーンな方法を見つけたと思いますが、想像力が必要になります。このアイデアは、「JavaScriptの良い部分」という本の実用的な手法から得られました。
newキーワードを使用する代わりに、次のようなクラスを作成できます。
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;
}
上記のオブジェクトをインスタンス化するには、次のように言います。
var objInst = Class(); // !!! NO NEW KEYWORD
この作業方法を念頭に置いて、次のようなシングルトンを作成できます。
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 };
}();
これで、次の呼び出しでインスタンスを取得できます
var obj = ClassSingleton.getInstance();
完全な「クラス」にさえアクセスできないので、これは最も近い方法だと思います。
@CMSと@zzzzBovはどちらもすばらしい答えを出しましたが、シングルトンパターンが一般的であったPHP / Zend Frameworkからのnode.js開発に移行したことに基づいて、独自の解釈を追加します。
次のコメント付きのコードは、次の要件に基づいています。
私のコードは@zzzzBovのコードに非常に似ていますが、コンストラクタにプロトタイプチェーンを追加し、PHPまたは同様の言語から来た人が従来のOOPをJavascriptのプロトタイプの性質に変換するのに役立つコメントを追加しました。「最も単純」ではないかもしれませんが、私はそれが最も適切であると信じています。
// 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'
技術的には、@ CMSによって提供されるコードで適切に示されているように、自己実行匿名関数自体がシングルトンです。ここでの唯一の問題は、コンストラクター自体が匿名の場合、コンストラクターのプロトタイプチェーンを変更できないことです。
Javascriptでは、「パブリック」および「プライベート」の概念は、PHPまたはJavaの場合のように適用されないことに注意してください。ただし、Javascriptの機能スコープの可用性に関するルールを活用することで、同じ効果を実現しています。
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
最も明確な答えは、Addy Osmani著の「JavaScriptのデザインパターンの学習」の本の答えです。
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;
}
};
})();
ES7が必要ですが、これが最も簡単でクリーンで直感的な方法だと思います。
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
ソースコードは以下からです:adam-bien.com
new Singleton()
これは、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();
私はいくつかのシングルトンが必要でした:
これが私が思いついたものです:
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は配列でなければなりません。したがって、空の変数がある場合は、[]を渡してください。
関数でウィンドウオブジェクトを使用しましたが、パラメーターを渡して独自のスコープを作成することもできました
名前と構成パラメーターは、window []が機能するための単なるStringですが、いくつかの単純な型チェックでは、window.nameとwindow.constructも可能です。
この方法については、クラスが再び新しいことはできないことを保証するだけです。
これにより、instanceof
op を使用できます。また、プロトタイプチェーンを使用してクラスを継承できます。これは通常のクラスですが、新しいインスタンスを作成することはできません。getInstance
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();
instance
メンバーを公開したくない場合は、クロージャーに入れてください。
以下は、シングルトンパターンを実装するためのウォークスルーのスニペットです。これはインタビューの過程で私に起こりました、そして私はどこかでこれを捉えるべきだと感じました。
/*************************************************
* 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
*******************************************************************/
同じことが私の要旨のページにあります
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
以下のTypeScriptの例のように、デコレータを使用してそれを行うことができます。
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
次に、次のようにシングルトンを使用します。
var myInstance = YourClass.singleton();
この記事の執筆時点では、JavaScriptエンジンでデコレーターをすぐに使用することはできません。JavaScriptランタイムでデコレーターを実際に有効にするか、BabelやTypeScriptなどのコンパイラーを使用する必要があります。
また、シングルトンインスタンスは「レイジー」で作成されます。つまり、初めて使用するときにのみ作成されます。
モジュールパターン:「より読みやすいスタイル」。どのメソッドがパブリックで、どのメソッドがプライベートであるかを簡単に確認できます
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");
今、あなたはパブリックメソッドを使うことができます
module.method2(); //->パブリックメソッドアラートでプライベートメソッドを呼び出しています( "こんにちはプライベートメソッド")
シングルトン:
クラスにインスタンスが1つしかないことを確認し、インスタンスへのグローバルなアクセスポイントを提供します。
シングルトンパターンは、特定のオブジェクトのインスタンスの数を1つに制限します。この単一のインスタンスはシングルトンと呼ばれます。
Singletonオブジェクトは、即時の無名関数として実装されます。この関数は、角かっこで囲み、さらに2つの角かっこを続けて、すぐに実行されます。名前がないため、匿名と呼ばれます。
サンプルプログラム、
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()
私にとって最もシンプル/クリーンなということは、Javaバージョンのディスカッションでよく議論されているように、単に理解し、口笛を吹かないことも意味します。
Javaでシングルトンパターンを実装する効率的な方法は何ですか?
私の観点からそこに最も簡単で/最もきれいに合う答えは:
https://stackoverflow.com/a/70824/1497139
そして、それはJavaScriptに部分的にしか翻訳できません。JavaScriptの違いは次のとおりです。
しかし、最新のECMA構文を考えると、次のように近づけることができます。
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;
}
}
使用例
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
結果の例
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;
}
クラスに参加している場合:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
テスト:
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
クラスを使用する場合:
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);
上記の出力は次のようになります。
console.log(x.name,x.age,y.name,y.age) // s 1 s 1
関数を使用してシングルトンを作成する別の方法
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);
上記の出力は次のようになります。
console.log(a.name,a.age,b.name,b.age)// s 1 s 1