シングルトン パターンの定義: クラスにはインスタンスが 1 つだけあることを確認し、それにアクセスするためのグローバル アクセス ポイントを提供します。
シングルトン モードは、一般的に使用されるモードです。スレッド プール、グローバル キャッシュ、ブラウザ ウィンドウ オブジェクトなど、1 つだけ必要なオブジェクトがいくつかあります。 js 開発では、シングルトン パターンも非常に広く使用されています。想像してみてください。ログイン ボタンをクリックすると、ページにログイン ボックスが表示されます。このフローティング ウィンドウは、ログイン ボタンを何度クリックしても 1 回しか作成されません。したがって、このログイン フローティング ウィンドウはシングルトン モードに適しています。
1. シングルトンモードの使用シナリオ
モードを使用する前に、このモードの使用シナリオを理解しておく必要があります。私はシングルトン パターンを長い間使ってきましたが、まだそれを知りません。それを使用する具体的な利点は何ですか?
1) 名前空間を分割するために使用できます (これはよく使用されます)
2). ブランチ技術を使用してブラウザ間の違いをカプセル化します (これはこれまで使用したことがありません。非常に新しいものです)
3) シングルトン モードを使用すると、コードをより一貫して編成でき、読みやすく、保守しやすくなります (これも使用されています)
2. 最も基本的なシングルトン パターン
最も単純なシングルトンは、実際にはオブジェクト リテラルです。関連するメソッドとプロパティのグループをまとめて整理します。
var Singleton = { attr1: true , attr2: 10 , method1 : function(){ alert('我是方法1'); }, method2 : function(){ alert('我是方法2'); } };
このオブジェクトは変更できます。プロパティとメソッドを追加できます。 delete 演算子を使用して既存のメンバーを削除することもできます。これは実際、オブジェクト指向設計の原則に違反しています。つまり、クラスは拡張できますが、変更すべきではありません。一部の変数を保護する必要がある場合は、クロージャで定義できます。
オブジェクト リテラルは、シングルトンを作成する方法の 1 つにすぎません。すべてのオブジェクト リテラルがシングルトンであるわけではありません。連想配列を模倣したり、データを保持するためにのみ使用されるオブジェクト リテラルは、明らかにシングルトンではありません。
3. クロージャを使用してシングルトンを作成します
閉鎖の主な目的はデータを保護することです
// 命名空间 var BHX = {} ; BHX.Singleton = (function(){ // 添加自己的私有成员 var a1 = true ; var a2 = 10 ; var f1 = function(){ alert('f1'); } var f2 = function(){ alert('f2'); } // 把块级作用域里的执行结果赋值给我的单例对象 return { attr1: a1 , attr2: a2 , method1 : function(){ return f1(); }, method2 : function(){ return f2(); } } ; })(); alert(BHX.Singleton.attr1); BHX.Singleton.method1();
このシングルトン モードはモジュール モードとも呼ばれます。これは、関連するメソッドと属性のバッチをモジュールに編成し、名前空間を分割する役割を果たすことができることを意味します。
4. シングルトン モードは名前空間
を分割するために使用されます。1)、グローバル宣言の変更を防止します
/*using a namespace*/ var BHX = {}; BHX.Singleton = { attr1: true , attr2: 10 , method1 : function(){ alert('我是方法1'); }, method2 : function(){ alert('我是方法2'); } }; BHX.Singleton.attr1; var attr1 = false;
こうすることで、同じ変数を外部で宣言しても、attr1が変更されることをある程度防ぐことができます。
2)、他のソースコードの変更を防止します
現在、Web ページ上の JavaScript コードでは、ライブラリ コード、広告コード、バッジ コードなど、複数のソースが使用されることがよくあります。独自のコードとの競合を避けるために、独自のコードをすべて含むオブジェクトを定義できます。
var XGP = {}; XGP.Common = { //A singleton with common methods used by all objects and modules } XGP.ErrorCodes = { //An object literal used to store data } XGP.PageHandler = { //A singleton with page specific methods and attributes. }
3)、特殊コードパッケージとして使用
多くの Web ページがある Web サイトでは、一部のコードはすべての Web ページで使用され、通常は別のファイルに保存されますが、一部のコードは特定の Web ページに固有であり、他の場所では使用されません。両方のタイプのコードを独自のシングルトン オブジェクトでラップするのが最善です。
フォームに機能を追加するために Javascript をよく使用します。スムーズに機能を低下させるために、まず Javascript に依存せず、通常の送信メカニズムを使用してタスクを完了する純粋な HTML ページを作成するのが一般的です。
XGP.RegPage = { FORM_ID: 'reg-form', OUTPUT_ID: 'reg-result', handleSubmit: function(e){ e.preventDefault(); //stop the normal form submission var data = {}; var inputs = XGP.RegPage.formEl.getElementByTagName('input'); for(var i=0, len=inputs.length; i<len; i++){ data[inputs[i].name] = inputs[i].value; } XGP.RegPage.sendRegistration(data); }, sendRegistration: function(data){ //make an xhr request and call displayResult() when response is recieved ... }, displayResult: function(response){ XGP.RegPage.outputEl.innerHTML = response; }, init: function(){ XGP.RegPage.formEl =$(XGP.RegPage.Form_ID); XGP.RegPage.outputEl = $(XGP.RegPage.OUTPUT_ID); //hijack the form submission addEvent(XGP.RegPage.formEl, 'submit', XGP.RegPage.handleSubmit); } } //invoke initialization method after the page load addLoadEvent(XGP.RegPage.init);
5. レイジーシングルトン
前述のシングルトン パターンにはもう 1 つの共通点があります。それは、スクリプトのロード時にシングルトン オブジェクトが作成されるということです。リソースを大量に消費する、または構成に費用がかかるシングルトンの場合は、使用する必要があるまでインスタンス化を延期する方が合理的です。
この手法は遅延読み込みです。
実装手順は次のとおりです:
1) すべてのコードをコンストラクター メソッド
に移動します。2) 呼び出しのタイミングを完全に制御します (getInstance が行うこととまったく同じです)
XGP.lazyLoading = (function(){ var uniqInstance; function constructor(){ var attr = false; function method(){ } return { attrp: true, methodp: function(){ } } } return { getInstance: function(){ if(!uniqInstance){ uniqInstance = constructor(); } return uniqInstance; } } })();
6. ブランチテクノロジー
分岐は、実行時に設定される動的メソッドでブラウザー間の差異をカプセル化するために使用される手法です。
// 分支单例 (判断程序的分支 <浏览器差异的检测>) var Ext = {} ; var def = false ; Ext.More = (function(){ var objA = { // 火狐浏览器 内部的一些配置 attr1:'FF属性1' // 属性1 // 属性2 // 方法1 // 方法2 } ; var objB = { // IE浏览器 内部的一些配置 attr1:'IE属性1' // 属性1 // 属性2 // 方法1 // 方法2 } ; return (def) ?objA:objB; })(); alert(Ext.More.attr1);
たとえば、Web サイトで xhr が頻繁に使用される場合、呼び出されるたびにブラウザー スニッフィング コードを再実行する必要があり、非常に非効率的になります。スクリプトの読み込み時にブラウザ固有のコードを一度識別する方が効率的です。これはまさに分岐テクノロジーが行うことです。もちろん、分岐テクノロジが常に効率的な選択肢であるとは限りません。2 つ以上の分岐のうち 1 つの分岐だけが使用され、他の分岐はメモリを占有します。
分岐テクノロジを使用するかどうかを検討するときは、時間の短縮とメモリ使用量の増加の長所と短所を比較検討する必要があります。
以下では分岐テクノロジーを使用して XHR を実装しています:
var XHR = (function(){ var standard = { createXhrObj: function(){ return new XMLHttpRequest(); } }; var activeXNew = { createXhrObj: function(){ return new ActiveXObject('Msxml2.XMLHTTP'); } }; var activeXOld = { createXhrObj: function(){ return new ActiveXObject('Microsoft.XMLHTTP'); } }; var testObj; try{ testObj = standard.createXhrObj(); return testObj; }catch(e){ try{ testObj = activeXNew.createXhrObj(); return testObj; }catch(e){ try{ testObj = activeXOld.createXhrObj(); return testObj; }catch(e){ throw new Error('No XHR object found in this environment.'); } } } })();
7. シングルトンモデルのデメリット
シングルトンについては十分に理解できたので、次にその欠点を見てみましょう。
シングルトン パターンは単一のアクセス ポイントを提供するため、モジュール間の結合が強くなる可能性があります。したがって、単体テストには適していません。
要約すると、シングルトンは名前空間の定義と分岐メソッドの実装のために予約されています。
7 つの異なる側面からシングルトン パターンを紹介しましたが、この記事が役に立てば幸いです。