これはどのようなパターンですか、それを行う必要がありますか?


9

私はフラッシュ開発とフラッシュcs5を使用してas3でゲームを作っています。すべてがオブジェクト指向です。他のクラスのすべてのインスタンス化へのプロパティ参照を持つ1つの「ゲートウェイ」クラスがあり、このゲートウェイクラスを新しいオブジェクトに渡すだけで、すべてのクラスにアクセスできるのではないかと思っていました。そのようです:

 var block:Block = new Block(gateway);

 //In the block class:
 this.gateway.player.setHealth(100);
 //Or:
 this.gateway.input.lock();

これはシングルトンパターンのようなものですか?これを行う必要がありますか?

回答:


13

これはコンテキストオブジェクトデザインパターンと呼ばれ、シングルトンパターンよりも優れています。

  • テストする関数にモックコンテキストを渡すことができるため、コンテキストオブジェクトはテストを支援します。シングルトンはそれを妨げます。シングルトンをモックするには、シングルトンではなくそれらを作る必要があるからです。
  • コンテキストオブジェクトは、「グローバル状態」を明示的にするため、理由付けが容易になります。関数がコンテキストオブジェクトをとらない場合は、グローバルコンテキスト状態を使用しないことがわかります。シングルトンやグローバル変数では、そのような保証はありません。
  • すべての関数呼び出しに別のパラメーターを追加するため、コンテキストオブジェクトを使用しない場合は、少し遅くなります。彼らはすることができより速くあなたがそれらを使用しない場合はグローバルに比べ、ほぼ常に速くシングルトンよります。
  • Contextオブジェクトは実装が簡単です。通常、ヒープまたはスタックに通常の方法で住んでいます。シングルトンには、多くの言語でのスレッド化に関連するトリッキーな問題があります。

つまり、これはシングルトンではなく、シングルトンよりもはるかに優れています。

ただし、それでも状態のクラップロードを渡し続けています。単一のローカル変数にすべてを保持しているという事実は、それをより明示的にしますが、それでもなお懸念の大きな融合を引き起こします。一つの責任のルールを覚えおいてください。プレーヤーと現在のレベルを所有するコンテキストが存在することは理にかなっています-それらは関連していますが、なぜ同じコンテキストがキーボード入力を所有するのですか?

たとえば、さまざまなレベルのコンテキストを検討します。

  • GameplayContext-プレイヤー、敵、レベルジオメトリなどを所有します。
  • InputContext-キーボードとマウスのハンドル、入力イベントなどを所有します。
  • GraphicsContext-テクスチャ、ウィンドウハンドルなどを所有します。
  • GlobalContext-GameplayContext、GraphicsContext、およびInputContextを所有します。これは、サービスロケータパターンを適用して、必要に応じて一部のコンテキストを他のコンテキストと交換できるようにする場所です。そして、おそらく、迅速な反復とテストのために、これは実際のグローバル変数である必要があります-それを使用するときはいつでも、あなたは技術的負債を積み上げていることに気づいてください。

これらのコンテキストは依然として懸念を幾分か和らげています-多分いくつかのイベントハンドラーはGameplayContextを取り、本当にプレーヤーだけが必要です-しかし責任は明確にレイアウトされています。GameplayContextを受け取るものはテクスチャをロードしないことを知っています。InputContextを取得するものはプレイヤーを殺せません。


+1良い答え。ただし、速度またはスレッド化の懸念の一部は、このコンテキストでは実際には適用されません(ActionScript3はスレッド化をサポートしておらず、C ++で機能する多くの速度向上メカニズムはAS3の使用時には適用されません)。
bummzack 2010年

私はAS3VMについてあまり知りませんが、ほとんどの動的言語では、ローカルを使用して/ /パッシング受信のコストはまだ速いグローバル(ハッシュ・ルックアップ)を調べるのコストよりも(配列参照)、そしてあるずっと速くよりそれを取得する関数(もののクラップロード)を呼び出す。だから私はそのアドバイスはまだ当てはまると思います。

0

これはシングルトンパターンのようには見えません。私の理解では、重要なゲームオブジェクトへの参照を含むオブジェクトをすべてのインスタンスに渡しています。

これがシングルトンパターンの場合、次のようになります。

AudioManager.getInstance().playSound(XY);

あなたのケースではあなたが持っているかもしれないのに対し:

this.gateway.getAudioManager().playSound(XY);

基本的には同じに見えますが、実際はそうではありません。のAudioManagerような新しい(拡張クラス)で置き換えるExtendedAudioManager場合は、シングルトンパターンを使用して壁にぶつかります。あなたのゲートウェイアプローチはそれでもうまくいきます。

あなたのアプローチの欠点は、あなたがgatewayいたるところを迂回しなければならないことです。サービスロケータパターン(でジョーWreschnigが提案したこのスレッド)、あなたの「ゲートウェイパターン」のための良い代替のように見えます。

場合によっては、設計しすぎず、単純で簡単な方法で実行する方が良い場合もあります。特に、小規模なプロジェクトやプロトタイプの場合はそうです。たぶん、あなたはそれをgatewayある種のグローバル変数にすることができます。Game.gatewayそれを実行します。


-2

シングルトンパターンを含むこの問題のほとんどの解決策は、静的変数の使用を含みます。プレーヤーが1つしかない場合は、Playerをシングルトンクラスにすることができます。つまり、Player.currentPlayerなどの方法でPlayerインスタンスにアクセスできます。しかし、多くの人々はシングルトンに激怒します。ResourceManagerまたは同様のクラスを使用して、さまざまな有用なグローバル変数またはpretty-darn-global変数への静的参照を含めることもできます。コードでは、どこにでもコードを渡してコードを拡張する代わりに、「ゲートウェイ」変数を静的にアクセス可能にすることもできます。


私がこの回答をして以来、質問は大幅に変更されており、編集する価値がないように思われます。
グレゴリーAvery-Weir

2
タイトルを除いて、質問では何も変わりませんでした。
bummzack 2010年

1
何?タイトル以外は何も変わっていません。-1
AttackingHobo 2010年

ここでタイトルを考えていたと思います。元のタイトルが「どうすればいいですか?」答えを出したときに、最初のタイトル/質問を誤って読んだ可能性があります。
グレゴリーAvery-Weir
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.