5

寄生コンストラクター パターンは、ファクトリ パターンとコンストラクター パターンの組み合わせと見なすことができます。ファクトリ パターンでは、オブジェクトを明示的に作成し、必要なプロパティとメソッドをオブジェクトに追加して、最終的にオブジェクトを返す関数を呼び出します。

function createPerson(name, age, job){
    var o = new Object();   //explicit object creation
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
            alert(this.name);
        };
    return o;
}

var person1 = createPerson(“Nicholas”, 29, “Software Engineer”);
var person2 = createPerson(“Greg”, 27, “Doctor”);

注意事項:

  • 明示的なオブジェクトが作成されて返されます
  • メソッドとプロパティが明示的に作成されたオブジェクトに追加されます
  • メソッドはnew演算子なしで呼び出されます

欠点: オブジェクトのタイプを識別できません。

任意の関数を演算子で呼び出すことにより、コンストラクターとして扱うことができますnewnew演算子なしで呼び出された場合、関数内では、thisオブジェクトはグローバル オブジェクト (windowブラウザー内) を指します。そして、関数がnew演算子で呼び出されると、最初に の新しいインスタンスを作成し、object次にthisobject を新しく作成されたオブジェクトに設定します。

コンストラクター パターンはメソッドとプロパティをthisオブジェクトに追加し、最終的にthisオブジェクトを返すため、後で演算子を使用してオブジェクトの型を識別できますinstanceOf

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
            alert(this.name);
        };
    }

    var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
    var person2 = new Person(“Greg”, 27, “Doctor”);

注意事項:

  • function はnewoperator で呼び出されます (JavaScript エンジンにコンストラクターとして扱わせるため)
  • オブジェクトは明示的に作成されず、代わりにthisオブジェクトが返されます

寄生コンストラクター パターンは、ファクトリ パターンに似たオブジェクトを明示的に作成して返し、コンストラクター パターンのような新しい演算子で呼び出されます。

function Person(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
            alert(this.name);
        };
    return o;
}

var friend = new Person(“Nicholas”, 29, “Software Engineer”);
friend.sayName(); //”Nicholas”

newただし、演​​算子を使用して関数を呼び出す方法はわかりません。instanceOfつまり、関数はオブジェクトを明示的に作成して返すため、演算子を使用してオブジェクトの種類を明示的に識別することはできません。

では、寄生コンストラクター パターンの何が優れているのでしょうか。特定のオブジェクト作成シナリオで活用または適切に使用できる技術的な微妙な点はありますか? または、オブジェクトを作成するためのプログラムによる別のアプローチはありますか?

4

2 に答える 2

3

あなたがファクトリーでスキップしている部分は、他のほとんどの言語では、ファクトリーは次のように行われるかどうかにかかわらず、複数の異なる種類の同様のオブジェクトを作成することになるということです。

var truck = carFactory("Truck");
var jeep  = carFactory("Jeep");

または次のように行います:

var piano = instrumentFactory.piano("Grand");
var bass  = instrumentFactory.bass("Upright");

または、必要なその他のインターフェイス...

または、ファクトリの責任は、依存性注入と潜在的なポリモーフィズムを通じて、小さなクラスから非常に大きなクラスを作成することです。

function createTank (gunType) {
    var armour = new Armour();
    armour.hp  = 120;

    var wheels = new ChainTracks();

    var driver = new Soldier();
    driver.hp  = 15;

    var gun = gunFactory(gunType);

    var tank = new Tank(armour, wheels, gun);
    tank.driver = driver;

    return tank; 
}

var ground_tank = createTank("cannon");
var aa_tank = createTank("flak_cannon");
var at_tank = createTank("depleted_uranium_lancer");

オブジェクトを作成し、そのプロパティを設定してオブジェクトを返すのと同じくらい単純な Factory がある場合、実際には違いはありません。

多くの特殊なコンポーネントを使用して何かをまとめることについて話している場合 (それらが注入されているか、ハードコードされているか)、または継承を扱っている場合に、違いが生じます。

正直なところ、これらのこと (オブジェクトの構成と継承) についてもっと学ぶことをお勧めします。

最終的には、ファクトリを使用した場合、または汎用オブジェクトを変更する関数を使用した場合、またはコードの途中で大量のクラスを使用した場合でも、完成したコードに違いはありません。 .. どのようにスライスしても、プログラムは問題なく実行されるか、停止します。

違いが生じるのは、コードの編成方法とコードの構成方法です。
ページ上にボタンを作成するだけであれば、ファクトリは必要ありません。
ページにフル機能の MP3 プレーヤーを作成する場合、6 つのボタン、プレイリスト、進行状況バー、およびトラック名、アーティスト名、カバー アートの表示が必要です...

...今こそ、工場のパターンを調べて、これらの部品を組み立てる方法を見つけ出し、1 つのことを要求し、組み立てラインから完成品を吐き出させる絶好の機会です。

于 2012-10-25T20:32:22.777 に答える
1

あなたの観点からは大きな違いはないと思いますが、さらに一歩進んで抽象的なファクトリ パターンを実装するか、ファクトリをポリモーフィングし始めると、新しいものを書くたびに多くの作業を節約できます。 .

JavaScript では、言語にはプライベートな値がないため、オブジェクトに任意の値を設定できるため、オブジェクトの OOP 標準をサポートするフレームワークを使用する場合、ファクトリは非常に強力であり、そのロジックのほとんどを基本クラスから継承できます。

編集

1 つ、私の目には、JavaScript とこれらのパターンに関して最も重要なことの 1 つはプロトタイピングです。

プロトタイピングは基本的に JavaScript でオブジェクトを定義する方法であり、ランタイムが実際にオブジェクトを認識し、他のオブジェクトと区別できるようにします。

基本的にプロトタイプのみを使用すると、次のようになります。

var Person = function(name){
    this.name = name
}; //constructor
Person.prototype.constructor = Person;
Person.prototype.name = 'Dave';
Person.prototype.getName = function() {
    return this.name;
}

いくつかのテストコード:

var dave = new Person('Dave');
console.log(dave.getName());​

そして最後に工場:

var PersonFactory = function(name) {
    return new Person(name);
}

通常、その注釈の問題は、保守性が低く、継承がないことです。

プロトタイプを構築するヘルパー関数を作成したり、プロトタイプ チェーンを構築したりすることもできます。基本的に、別のオブジェクトを取り込むオブジェクトを定義し、他のオブジェクトのメンバーを目的のクラス オブジェクトのプロトタイプに解決し、継承などのあらゆる種類の可能性を残します。

いくつかの例がここにあります: http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures

mootools がクラスを処理する方法が気に入っています。

var MyClass = new Class({
Extends: MyOtherClass
Implements: [MyInterface, MyOtherInterface],

myPublicValue: null,
myOtherValue: null,


initialize: function() {
    //constructor
},

doStuff: function() {
    return 'stuff done';
}

});

mootools クラス システム自体の欠点: -Closure Compiler は末尾のコンマを好みません。コードにコンマを残す傾向があります。

- mootools クラスのオートコンプリートをサポートする IDE はほとんどありません (ファイル内でプロトタイプに注釈が付けられていないため、クラスをプロトタイプ化されたファイルに解決するスクリプトを使用して解決できます)。

これで、あなたが行くことができる設計上の決定がたくさんあります。ファクトリが独自のプロトタイプ ヘルパー クラスから継承できるようにし、プロトタイプ ヘルパー クラスを使用して実際のファクトリを作成します (ここではいくつかの再帰)。作成時に各オブジェクトを解決できます。 (遅延読み込みのように) またはページの読み込み時にすべてのクラス オブジェクトを解決します (継承に入る場合は、派生元のクラスのほとんどの実装で最初に解決する必要があることに注意してください)、または可能な方法で行います。

それが役に立ったことを願っています:)

(そして、今は英語が下手でごめんなさい、今夜はかなり疲れていますxD)

于 2012-10-25T08:54:58.493 に答える