1

JavaScript で、実行時間の長いアプリケーションでオブジェクトをインスタンス化したいと考えています。オブジェクトは、ミックスインで拡張できるようにする必要があります。いくつかの設計上の制限があります。

  1. ミックスインは既存のメソッドをオーバーライドする可能性があります
  2. ミックスインは新しいメソッドを提供するかもしれません
  3. 特定の mixin メソッドはスーパーを参照できる必要があるため、複数の mixin にまたがる同名の動作を一緒にパイプすることができます
  4. ミックスインを追加するよりも、オブジェクトからミックスインを削除する方が難しくないはずです
  5. ミックスインをオブジェクトにプッシュしたい。つまり、元のオブジェクトへの保持された参照が古くなっているため、オブジェクトをラップ/装飾しないことを望んでいます。

JS では通常、ミックスインはそのメソッドをオブジェクトに直接コピーします。新しい動作を簡単にアンプラグしたくない場合は、これで問題ありません。アプリケーションは無期限に実行される可能性があるため、これらの動作はいつでも簡単に追加または削除できる必要があり、オブジェクトをいじって動作を追加しても、後で簡単に削除することはできません。

私は大まかに「ミックスイン」について言及しています。主な考え方は、オブジェクトは、一緒にパイプできる動作をプラグまたはアンプラグできるということです。メカニズム自体はそれほど重要ではありません。Rackに精通している方の中には、これがいかに便利かをご存知の方もいらっしゃるでしょう。

var tim = new Person('Tim'); //at 12:00pm
tim.eat()                    //at 12:00pm -- native Person behavior
tim.addBehavior(husband)     //at 12:00pm
tim.kissWife()               //at 12:00pm -- husband behavior
tim.addBehavior(father)      //at 12:00pm
tim.addBehavior(hungry)      //at 12:00pm -- augments the native eat behavior
tim.addBehavior(bowler)      //at 5:00pm
tim.bowl()                   //at 5:00pm
tim.performDailyDuties()     //at 5:00pm -- includes husband and father duties
tim.removeBehavior(bowler)   //at 5:00pm -- easily remove behavior
tim.bowl()                   //at 5:01pm -- error!
tim.kissWife()               //at 5:01pm

したくないです...

var husbandTim = new Husband(tim)
var bowlerTim  = new Bowler(husbandTim)

...特定の動作を削除するのが難しくなるためです。さらに、 への参照を保持しているすべての場所についてはどうでしょうかtim。それらの場所は、新しい動作を認識しません。

残念ながら、JS には、これを簡単にするために私が知っているものは何もありません。ES6 はこれを可能にするプロキシを提供しますが、より単純なアプローチを見逃していたのではないかと思っています。

後で削除するのと同じくらい簡単にプラグインの動作を追加することを容易にする設計パターンまたはメカニズムは何ですか? これらの線に沿って何かを行うフレームワークはありますか?

4

1 に答える 1

0

オブジェクトにミックスインを追加し、上書きされたメソッドを呼び出すことができるUberprotoと呼ばれる ES5 継承ライブラリを少し前に作成しました。例えば:

var PersonObject = {
    init : function(name) {
        this.name = name;
    },

    fullName : function() {
        return this.name;
    }
};

Proto.mixin({
    fullName : function() {
        return 'My name is: ' + this._super();
    }
}, PersonObject);

// Create a plain object without calling the constructor
var instance = Object.create(PersonObject);
instance.name = 'Dude';
console.log(instance.fullName()); // 'My name is: Dude'

ミックスインを作成する対象に注意すれば、実際には非常にうまく機能することがわかりました。ミックスインを削除する必要はありませんでしたが、追加する前に元のメソッドへの参照を保存するのと同じくらい簡単なはずです。

var PersonObject = {
    init : function(name) {
        this.name = name;
    },

    fullName : function() {
        return this.name;
    }
};

var backup = {
    fullName: PersonObject.fullName
};

Proto.mixin({
    fullName : function() {
        return 'My name is: ' + this._super();
    }
}, PersonObject);

// Create a plain object without calling the constructor
var instance = Object.create(PersonObject);
instance.name = 'Dude';
console.log(instance.fullName()); // 'My name is: Dude'

// Restore old mixin
PersonObject.fullName = backup.fullName;
var instance = Object.create(PersonObject);
instance.name = 'Dave';
console.log(instance.fullName()); // 'Dave'

したがって、必要なのは、その機能をより一般的なものにラップすることだけです。

于 2013-05-03T18:07:59.037 に答える