35

アプリに依存性注入を提供するためにRequireJSをどれだけ伸ばすことができますか?例として、シングルトンになりたいモデルがあるとします。自己強制型のgetInstance()タイプのシングルトンではなく、コンテキスト強制型のシングルトン(「コンテキスト」ごとに1つのインスタンス)。私は次のようなことをしたいのですが...

require(['mymodel'], function(mymodel) {
   ...
}

そして、mymodelをMyModelクラスのインスタンスにします。これを複数のモジュールで行う場合は、mymodelを同じ共有インスタンスにします。

mymodelモジュールを次のように作成することで、この作業を成功させました。

define(function() {
    var MyModel = function() {
        this.value = 10;
    }
    return new MyModel();
});

このタイプの使用法は予想され、一般的ですか、それともRequireJSを悪用していますか?RequireJSを使用して依存性注入を実行するためのより適切な方法はありますか?ご協力いただきありがとうございます。まだこれを把握しようとしています。

4

3 に答える 3

60

これは実際には依存性注入ではなく、サービスの場所です。他のモジュールは文字列「key」によって「クラス」を要求し、「サービスロケーター」(この場合はRequireJS)が接続されているインスタンスを取得します。それらを提供します。

依存性注入には、MyModelコンストラクターを返すことが含まれます。つまりreturn MyModel、中央の構成ルートで、のインスタンスを他のインスタンスに注入しMyModelます。これがどのように機能するかのサンプルをここにまとめました:https ://gist.github.com/1274607 (以下にも引用)

このようにして、コンポジションルートは、それを必要とするクラスごとに、単一のインスタンスを渡すMyModel(つまり、シングルトンスコープにする)か、新しいインスタンスを渡すか(インスタンススコープにする)、またはその間の何かを決定します。そのロジックは、MyModelの定義にも、そのインスタンスを要求するクラスにも属していません。

(補足:私は使用していませんが、wire.jsはJavaScript用の本格的な依存性注入コンテナであり、かなりクールに見えます。)


RequireJSを使用するのと同じように使用することで、必ずしもRequireJSを悪用しているわけではありませんが、実行していることは少し回りくどいように見えます。つまり、クラスの新しいインスタンスを返すよりもクラスを宣言します。なぜ次のことをしないのですか?

define(function () {
    var value = 10;

    return {
        doStuff: function () {
            alert(value);
        }
    };
});

あなたが見逃しているかもしれないアナロジーは、モジュールは他のほとんどの言語の「名前空間」と同等ですが、関数と値を付加できる名前空間です。(JavaやC#よりもPythonに似ています。)これらはクラスと同等ではありませんが、ご覧のとおり、モジュールのエクスポートを特定のクラスインスタンスのエクスポートと等しくすることができます。

したがって、関数と値をモジュールに直接アタッチすることでシングルトンを作成できますが、これは静的クラスを使用してシングルトンを作成するようなものです。柔軟性が低く、一般的にベストプラクティスではありません。ただし、ほとんどの人はモジュールを「静的クラス」として扱います。依存性注入用のシステムを適切に設計するには、JavaScriptの標準ではない、最初から多くのことを考える必要があるためです。


https://gist.github.com/1274607インラインは次のとおりです。

// EntryPoint.js
define(function () {
    return function EntryPoint(model1, model2) {
        // stuff
    };
});

// Model1.js
define(function () {
    return function Model1() {
        // stuff
    };
});

// Model2.js
define(function () {
    return function Model2(helper) {
        // stuff
    };
});

// Helper.js
define(function () {
    return function Helper() {
        // stuff
    };
});

// composition root, probably your main module
define(function (require) {
    var EntryPoint = require("./EntryPoint");
    var Model1 = require("./Model1");
    var Model2 = require("./Model2");
    var Helper = require("./Helper");

    var entryPoint = new EntryPoint(new Model1(), new Model2(new Helper()));
    entryPoint.start();
});
于 2011-10-10T04:15:47.067 に答える
3

DI / IOCに真剣に取り組んでいる場合は、wire.jsに興味があるかもしれません:https ://github.com/cujojs/wire

サービスの再配置(Domenicが説明しているように、RequireJSの代わりにcurl.jsを使用)とDI(wire.jsを使用)を組み合わせて使用​​します。テストハーネスでモックオブジェクトを使用する場合、サービスの再配置は非常に便利です。DIは、他のほとんどのユースケースに最適な選択のようです。

于 2011-10-20T13:01:24.890 に答える
2

自己強制型のgetInstance()タイプのシングルトンではなく、コンテキスト強制型のシングルトン(「コンテキスト」ごとに1つのインスタンス)。

静的オブジェクトにのみお勧めします。require/defineブロックで使用してロードするモジュールとして静的オブジェクトを使用することはまったく問題ありません。次に、静的プロパティと関数のみを含むクラスを作成します。これで、PI、E、SQRTなどの定数と、round()、random()、max()、min()などの関数を持つMathObjectに相当するものが得られます。いつでも注入できるユーティリティクラスを作成するのに最適です。

これの代わりに:

define(function() {
    var MyModel = function() {
        this.value = 10;
    }
    return new MyModel();
});

インスタンスを作成する場合は、静的オブジェクトのパターンを使用します(オブジェクトがインスタンス化されることのない値が常に同じであるオブジェクト)。

define(function() {
    return {
       value: 10
    };
});

また

define(function() {
    var CONSTANT = 10;
    return {
       value: CONSTANT
    };
});

インスタンス(新しいMyModel();を返すモジュールを使用した結果)を渡す場合は、初期化関数内で、現在の状態/コンテキストをキャプチャする変数を渡すか、次の情報を含むオブジェクトを渡します。モジュールが知る必要のある状態/コンテキスト。

于 2012-09-11T04:02:27.643 に答える