web-dev-qa-db-ja.com

JavaScriptのモジュールパターンはシングルトンの作成にのみ役立ちますか?

一部の記事( JavaScriptモジュールパターンの詳細Mastering The Module Pattern )は、以下のスニペット(Addy Osmaniの「Learning JavaScript Design Patterns」から)のようなJavaScriptでのモジュールの定義について説明しています。

var testModule = (function () {
    var counter = 0;
    return {
        incrementCounter: function () {
            return counter++;
        },
        resetCounter: function () {
           console.log( "counter value prior to reset: " + counter );
           counter = 0;
        }
    };
})();

モジュールの使用:

testModule.incrementCounter();
testModule.resetCounter(); 

この場合、コード全体で単一のインスタンスを使用しているため、このモジュールの実装は、シングルトンを作成する場合にのみ有用です。

このモジュールパターンのバリエーションを使用できるのは本当ですか、それとも他のユースケースがありますか?

8
alinaish

私は主張しますno-ish。シングルトン以外を返す場合、それがreally "モジュールパターン"であるかどうかはわかりません。ただし、同じ「パターン」を使用して他のことを実行することもできます。

モジュールは、戻り値の作成に使用される内部変数からグローバルスコープを保護します。ただし、戻り値自体がコンストラクターを含む関数である場合もあります。

そのために、すべてのクラスのインスタンスにアクセスさせたい何らかの「プライベートスタティック」クラスメンバーが必要な場合は、モジュールパターンでそれを実現できます。

ばかげた例として、Counterクラスを構築していて、個々のCounterが特定のイベントを追跡する必要があるが、alsoが必要な場合- protectedTotalCountEventsすべてのCounterオブジェクトにわたって、これを行うことができます:

var Counter = (function() {
  var totalcount = 0;

  var constructor = function() {
    var count = 0;
    this.increment = function() { count += 1; totalcount += 1; };
    this.getCount = function() { return count; };
  };

  constructor.getTotalCount = function() { return totalcount; };
  return constructor;
})();

その後、次のように使用できます。

var counterA = new Counter();
var counterB = new Counter();

counterA.increment(); counterA.increment();
counterB.increment(); counterB.increment(); counterB.increment();

console.log(counterA.getCount(), counterB.getCount(), Counter.getTotalCount());

そしてあなたは見るでしょう:

> 2 3 5

ただし、基になるtotalcountへのアクセスはCounterのインスタンスに制限されます。


覚えておいてください、ファクトリー・パターンは、スタイル/構文の違いだけで、同じ種類のことを達成できます。 「モジュール」のように見えるようにファクトリーを変更すると、ほとんどの場合new ...を使用してインスタンスを作成できます。これは、とにかくいくつかのサークルではタブーです。

4
svidgen

モジュールパターンを使用してanythingを返すことができます。これは、モジュールのインスタンス化中にグローバルな汚染を回避するための単なる方法です。関数またはコンストラクターを生成するために使用され、必要に応じて何度でも使用できることがよくあります。

var module = (function (){
    ...scoped stuff...

    return function () {
        ...do stuff with scoped stuff...
    };
}());

他の場所:

var foo = new module();
var bar = new module(baz);
//or
var fizz = module(buzz);

モジュールは単なるIIFEです。関数を再利用する場合は、関数として宣言し、再利用して複数のモジュールをインスタンス化します。

function moduleFactory(...) {
  ...
  return {
    ...
  };
}
var module1 = moduleFactory(1);
var module2 = moduleFactory(2);

この時点では、「モジュールパターン」は使用していません。IIFEは1つの値しか返さないため(ES2015 +スプレッドなどを無視して)、複数のインスタンス化を処理することを意図したものではありません。

0
zzzzBov