ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript デザイン パターン シリーズ 2: シングルトン パターン

JavaScript デザイン パターン シリーズ 2: シングルトン パターン

不言
不言オリジナル
2018-04-02 13:55:091558ブラウズ

この記事では、JavaScript 設計パターンの 2 番目のシリーズ: シングルトン モードを紹介します。興味のある方はぜひご覧ください

シングルトン モード

前書き: このシリーズのコードは、GitHub アドレス https://github にアップロードされています。 .com/HolyZheng/…

シングルトンパターンとは何ですか?

シングルトン パターンの定義: クラスにはインスタンスが 1 つだけあり、グローバルにアクセスできます单例模式的定义:一个类仅有一个实例,并且可以在全局访问
什么时候需要用到单例模式呢?其实单例模式在日常开发中的使用非常的广泛,例如各种浮窗、像登录浮窗等,无论我们点击多少次,都是同一个浮窗,浮窗从始至终只创建了一次。这种场景就十分适合运用单例模式。


代码实现

我们创建一个“最老的人”的类,很明显,“最老的人”有且只有一个。这很符合我们单例模式的运用场景。我们先来看看完整代码:

var oldestMan = function (name) {
  this.name = name;
}

oldestMan.prototype.getName = function () {
  console.log(this.name);
}
//引入一个代理函数和闭包的概念
var createOldestMan = (function () {
  var instance;
  return function (name) {
      if (!instance) {
         instance = new oldestMan(name);
      }
      return instance;
  }
})();

var personA = createOldestMan("holz");
var personB = createOldestMan("Amy");
personA.getName();  //  holz
personB.getName();  //  holz

我们可以在控制台上看到即使调用了两次createOldestMan并且赋了不一样的值,但两次getName()输出的都是第一次的“holz”。这就是单例模式。

代码看不太懂?没关系,现在给大家一一讲解。
首先我们创建了一个oldestMan类,创建了一个name属性。然后我们通过 prototype 给它添加一个getName()方法用来获取oldestMan的名字,相信到这里大家都是懂的,然后下面一段代码就是重点了,也比较难理解。我们打这段代码单独拿出来将一下。

//引入一个代理函数和闭包的概念
var createOldestMan = (function () {
  var instance;
  return function (name) {
      if (!instance) {
         instance = new oldestMan(name);
      }
      return instance;
  }
})();

首先,我们不用管什么是代理函数,之所以叫它代理函数是因为它辅助我们实现单例模式的效果,这段函数第一个关键点是 createOldestMan() 是一个立即执行函数。立即函数在声明的时候就会立即执行,也就是在声明createOldestMan的时候这个函数就会执行,它会声明一个instance 变量,然后返回一个函数给createOldestMan。createOldestMan就相当于:

var createOldestMan = function (name) {
      if (!instance) {
         instance = new oldestMan(name);
      }
      return instance;
  }

第二个关键点是:这里利用了 闭包 的概念。

闭包是什么呢?我只需要记住当函数在定义时的语法作用域之外被调用,却还能访问定义时的语法作用域时,就是产生了闭包。

我们来看一下我们的代码,函数先定义了一个instance,然后再返回一个function(name),这个function(name)里面用到了instance变量。在正常情况下,在立即执行函数执行之后,instance变量就会被JavaScript的垃圾回收机制回收,但是因为function(name)被返回到了外部,而function(name)随时会被调用,随时会访问到instance变量,所以instance变量被保留在了内存中。这就产生了闭包。也就是说,function(name)被赋值给了外部的createOldestMan,在外部的语法作用域中执行,但还可以访问到定义时内部的语法作用域中的instance。

所以在 立即执行函数闭包シングルトン パターンを使用する必要があるのはどのような場合ですか?実際、シングルトン モードは、ログイン フローティング ウィンドウなどのさまざまなフローティング ウィンドウなど、日常の開発で広く使用されています。何度クリックしても同じフローティング ウィンドウであり、フローティング ウィンドウは一度しか作成されません。初めから最後まで。このシナリオは、シングルトン モードの使用に非常に適しています。

コードの実装

「最年長者」のクラスを作成します。明らかに、「最年長者」は 1 人だけです。これは、シングルトン モデルのアプリケーション シナリオと非常に一致しています。まず完全なコードを見てみましょう:

var singleObj;
var createSingleton = function (fn) {
  return function (text) {
    if (!singleObj) {
      singleObj = new fn (text);
    }
    return singleObj;
  }
}

createOldestMan が 2 回呼び出され、異なる値が割り当てられているにもかかわらず、getName() / code> 出力はすべて最初の「holz」です。これがシングルトンパターンです。

コードが理解できない?構いません、これから一つずつ説明していきます。

まず、oldestMan クラスと name 属性を作成しました。次に、prototype を介して getName() メソッドを追加して、oldestMan の名前を取得します。ここでは誰もが理解していると思いますが、次のコード部分が焦点になりますが、これはさらに困難です。理解する。このコード部分を取り出して、個別に見てみましょう。
var oldestMan = function (name) {
  this.name = name;
}

oldestMan.prototype.getName = function () {
  console.log(this.name);
}

//一个通用的代理函数
var singleObj;
var createSingleton = function (fn) {
  return function (text) {
    if (!singleObj) {
    singleObj = new fn (text);
    }
    return singleObj;
  }
}

var person_1 = createSingleton(oldestMan)("holz");
var person_2 = createSingleton(oldestMan)("tom");
person_1.getName(); //holz
person_2.getName(); //holz

まず、プロキシ関数が何であるかについて心配する必要はありません。プロキシ関数と呼ばれる理由は、この関数の最初の重要な点です。 createOldestMan() は即時実行関数です。即時関数は、宣言されるとすぐに実行されます。つまり、この関数は、createOldestMan が宣言されると実行され、インスタンス変数を宣言してから、createOldestMan に関数を返します。 createOldestMan は次と同等です:

rrreee

2 番目の重要な点は、closure の概念がここで使用されていることです。

閉鎖とは何ですか?関数が定義された構文スコープの外で関数が呼び出された場合に、クロージャが発生するが、関数が定義された構文スコープには引き続きアクセスできることを覚えておく必要があります。

コードを見てみましょう。関数は最初にインスタンスを定義し、次に関数(名前)を返します。この関数(名前)ではインスタンス変数が使用されます。通常、関数の実行直後はJavaScriptのガベージコレクション機構によりインスタンス変数がリサイクルされますが、関数(名前)は外部に返され、関数(名前)はいつでも呼び出されるため、インスタンス変数はいつでもアクセスされるため、インスタンス変数はメモリに保持されます。これによりクロージャが作成されます。つまり、function(name) は外部の createOldestMan に割り当てられ、外部構文スコープで実行されますが、定義時に内部構文スコープでインスタンスにアクセスすることもできます。

そのため、Immediately run functionClosure のアクションでは、インスタンスは 1 回だけ適用されます。つまり、インスタンスは 1 つだけです。つまり、createOldestMan("...")を何度実行しても、インスタンスは初回の値しか取得されません。したがって、インスタンスがインスタンス化されているかどうかを判断し、インスタンスがインスタンス化されている場合はインスタンスを返します。これにより、クラスのインスタンスが 1 つだけ存在するという効果が得られます。

ユニバーサル シングルトン パターン


コードを変更することもできます。開発ではシングルトンが 1 つだけではない可能性があるため、すべてのシングルトンに対してコードをユニバーサルにする必要があります。どこを変更すればよいでしょうか?そうです、プロキシ機能を変更してください。 OldestMan()に限らず、プロキシ関数内でoldestMan()を抽出し、パラメータの形式で渡す値を変更するだけです。

rrreee

このようにして、シングルトンをパラメータとして渡し、それを使用してさまざまなシングルトンを実装できます。
完全なコードは次のとおりです:

rrreee🎜同様に、createSingleton が再度呼び出され、別の値が渡された場合でも、出力は最初の「holz」のままです。 🎜🎜🎜概要🎜🎜 シングルトン パターンの定義: クラスにはインスタンスが 1 つだけあり、グローバルにアクセスできます。 🎜適用可能なシナリオ: 実際、シングルトン モードは、さまざまなフローティング ウィンドウ、ログイン フローティング ウィンドウなど、日常の開発で広く使用されています。何度クリックしても、同じフローティング ウィンドウです。フローティング ウィンドウは一度だけ作成されます。 。このシナリオは、シングルトン モードの使用に非常に適しています。 🎜🎜関連する推奨事項: 🎜🎜🎜JavaScript デザイン パターン シリーズ 1: ファクトリ パターン🎜🎜🎜🎜🎜🎜🎜🎜

以上がJavaScript デザイン パターン シリーズ 2: シングルトン パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。