JavaScript設計モデルと開発実践シリーズの単例モデル


本シリーズは『JavaScript設計モードと開発実践』(著者:曽探)学習総括であり、深く理解したい場合は、著者原版をサポートしてください.

単一モード


単一モードの実装


一例パターンの は、である.単例モードはよく使われるモードで、いくつかのオブジェクトは私たちが1つしか必要としないことがよくあります.例えば、ログインウィンドウ、このウィンドウは唯一で、私たちが何回ログインボタンをクリックしても、このウィンドウは1回しか作成されません.そうすれば、このウィンドウは単例モードで作成するのに適しています.
標準的な単一インスタンス・モードを実装するのは複雑ではありません. を使用して、現在クラスにオブジェクトが作成されているかどうかを示します.もしそうであれば、次のクラスのインスタンスを取得するときに、前に作成したオブジェクトに直接戻ります.コードは次のとおりです.
var Singleton=function(name){
    this.name=name;
    this.instance=null;
};
Singleton.prototype.getName=function(){
    alert(this.name);
};
Singleton.getInstance=function(){
    if(!this.instance){
        this.instance=new Singleton(name);
    }
    return this.instance;
};
var a=Singleton.getInstance('sven1');
var b=Singleton.getInstance('sven2');

alert(a===b);//true

または
var Singleton=function(name){
    this.name=name;
};
Singleton.prototype.getName=function(){
    alert(this.name);
};
Singleton.getInstance=(function(){
    var instance=null;
    return function(name){
        if(!instance){
            instance=new Singleton(name);
        }
        return instance;
    }
})();

私たちはSingletonを通ります.getInstanceはSingletonクラスの一意のオブジェクトを取得するために使用され、この方法は比較的簡単であるが、 である.従来のnew XXXによる取得対象とは異なり、ここではSingletonを用いる.getInstanceはオブジェクトを取得するため、このコードの意味は大きくありません.

透明な単一モード


我々の現在の目標は の単一クラスを実現することである.
var CreateDiv = (function() {
    
    var instance;
    
    var CreateDiv = function(html) {
        if (instance) {
            return instance;
        }
        this.html = html;
        this.init();
        return instance = this;
    };
    CreateDiv.prototype.init = function() {
        var div = document.createElement('div');
        div.innerHtml = this.html;
        document.body.appendChild(div);
    };
    return CreateDiv;
})()

var a = new CreateDiv('sven1');
var b = new CreateDiv('sven2');
alert(a===b);//true

透明な単一クラスの作成が完了しましたが、同じようにいくつかの欠点があります.Instanceをカプセル化するために,自己実行の匿名関数と閉パッケージを用い,この匿名関数を真のSingleton構造方法に戻すことで,いくつかのプログラムの複雑さを増し,読むのも快適ではない.ある日、この単一のクラスを通常のクラスにする必要があると仮定します.つまり、複数のインスタンスを生成することができます.CreateDivコンストラクション関数を書き直さなければなりません.この変更は多くの不要な面倒をもたらします.

エージェントによる単一モードの実装


まず一般的なCreateDivクラスを作成します.
var CreateDiv = function(html) {
  this.html = html;
  this.init();
};
CreateDiv.prototype.init = function() {
  var div = document.createElement('div');
  div.innerHtml = this.html;
  document.body.appendChild(div);
};

次に、プロキシクラスProxySingletonCreateを導入します.
var ProxySingletonCreate = (function() {
  var instance;
  return function(html) {
    if (!instance) {
      instance = new CreateDiv(html);
    }
    return instance;
  }
})();

var a = new ProxySingletonCreate('sven1');
var b = new ProxySingletonCreate('sven2');
console.log(a === b);

これにより、CreateDivProxySingletonCreateとを組み合わせて、単例モードの効果を実現した.

JavaScriptでの単一モード


前述したいくつかの単一モードの実装は、 に近い実装であり、単一オブジェクトは から作成される.しかし、JavaScriptは実際には の言語であるため、単例モデルの概念を生み出すことは意味がない.一例パターンの は、である. は単一例モードではないが、実際の応用では、グローバル変数を単一例として使用することが多い.例:
var a = {};

グローバル変数は、上記の2つの条件を満たすことができるが、 を容易にもたらすという多くの問題がある.一般的な開発者として、グローバル変数の使用を減らす必要があります.いくつかの方法で グローバル変数による命名汚染を行うことができます.

ネームスペースの使用


最も簡単な方法は依然として 方式を使用しています.
var namespace1={
    a:function(){
    },
    b:function(){
    }
};

また、名前空間を動的に作成することもできます.
var myApp = {};
myApp.namespace = function(name) {
  var parts = name.split('.');
  var current = myApp;
  for (var i in parts) {
    if (!current[parts[i]]) {
      current[parts[i]] = {};
    }
    current = current[parts[i]];
  }
};

myApp.namespace('event');
myApp.namespace('dom.style');

console.log(myApp);

クローズドパッケージを使用したプライベート変数のカプセル化

var user=(function(){
    var _name='sven',_age=29;
    return {
        getUserInfo:function(){
            return _name+'_'+_age;
        }
    }
})();

不活性単例

とは、必要に応じてオブジェクトインスタンスを作成することを意味します. は、実際の開発において である単一のモードの重点である.まず、管理リストの論理オブジェクトを抽出します.
var getSingle=function(fn){
    var result;
    return function(){
        return result||(result=fn.apply(this.arguments));
    }
};

オブジェクトを作成する方法fnは、getSingleにパラメータとして入力される.
var getSingle = function(fn) {
  var result;
  return function() {
    return result || (result = fn.apply(this.arguments));
  };
};

var createLoginLayer = function() {
  var div = document.createElement('div');
  div.innerHTML = '     ';
  div.style.width = '100px';
  div.style.height = '100px';
  div.style.background = 'red';
  document.body.appendChild(div);
  return div;
};

aa = getSingle(createLoginLayer);
aa();
result変数は、 に存在するため、決して破棄されません.将来のリクエストでresultが割り当てられている場合、彼はこの値を返します.以下にプレゼンテーションのアドレスを示します.
不活性単例プレゼンテーションアドレスその他のプレゼンテーションアドレス