5

実際には、Observer パターンの実装は、再入可能性による悪い動作をどのように回避するのでしょうか?

「悪い動作」を明確にするために、パターン内のサブジェクトがメソッド MethodA() と MethodB()、イベント OnMethodA() と OnMethodB()、および 1 つ以上のオブザーバーをシングルスレッドの同期実装で持つ状況を考えてみましょう。

  • Subject.MethodA() が呼び出され、
  • Subject は MethodA() に対して行うことを行い、次にすべての Observer に対して OnMethodA() を呼び出します。
  • Observer1 は OnMethodA() イベントを取得し、Subject.MethodB() を呼び出します。
  • Subject は MethodB() に対して行うことを行い、次にすべての Observer に対して OnMethodB() を呼び出します。

この時点で、まだ OnMethodA() の通知の途中ですが、すべてのオブザーバーに対して OnMethodB() を呼び出しています。これは、リスト内の Observer1 の後のすべてのオブザーバーが、「OnMethodA()」の前に「OnMethodB()」を参照することを意味します。これは悪い動作です。

  • Observer2 (Observer1 について何も知らない開発者によって作成された) は、OnMethodB() イベントを取得し、Subject.MethodA() を呼び出します。
  • …永遠に。Subject.MethodA() -> Observer.OnMethodA() -> Subject.MethodB() -> Observer.OnMethodB() -> Subject.MethodA() -> など…</li>

ここで、スタックをオーバーフローさせます。それは悪い振る舞いです。

最初から非同期のキューベースの通知を使用して設計した場合、または通知中に Subject への呼び出しで例外をスローした場合は、これを回避できます。これは非常に簡単に理解できます。私を悩ませているのは、これがパターンを実装する際のベスト (または実際には唯一の) プラクティスとして言及されているのをほとんど見たことがないことです。「オブザーバーパターンリエントラント」をグーグルで検索するには、すでに問題を認識している必要があります。その検索の結果は、パターンに関する本の警告ではなく、問題に遭遇した人だけのようです。

それで、私は何かを逃していますか? 実際には、Observer パターンの実装は、再入可能性による悪い動作をどのように回避しますか?

4

3 に答える 3

1

再入可能性を回避するための「修正」の 1 つは、フラグisResponding, isUpdating, を設定することです。再入を避けるためにチェックしてください。ps 作りますvolatile

私はこれをエレガントな解決策や良い解決策とさえ主張していません。しかし、時々それは行く方法です。

于 2013-03-04T02:14:05.097 に答える
0

無限再帰に関するこの質問は、オブザーバー パターンと、GUI アプリケーションでモデル ビュー コントローラー (MVC) パターンを使用する場合に注意すべき重要な問題です。以前の作業では、これを防ぐためにフラグを使用する方法を使用しようとしましたが、フラグを使用すると複雑さが増し、期待どおりに動作しない場合があることがわかりました。

私にとってうまくいくことがわかり、自信を持って5年以上使用してきた解決策は、コードがモデル変更イベントに応答してビューの状態を更新するときに、コントローラーのサイクルを断ち切ることです。ビューを変更することによって生成されるイベントを観察していません。あなたの状況でそれが不可能な場合は、フラグを使用するのが最善の策です。

簡単な例は、データ用の単一の文字列、ビュー用のテキスト フィールド、およびそれらの間のコントローラー オブジェクトを持つモデルです。ユーザーが文字列を変更すると、モデルに文字列を更新するように指示するコントローラーに通知します。モデルの変更は、テキスト フィールドを更新するコントローラーに通知します。ここは注意が必要です。コントローラーは、ユーザーのアクションまたはビューのコンテンツの独自の更新によって生成されたビューからのイベントを区別できる必要があります。リッスンするビューから適切なイベントを選択するだけで済む場合もあれば、コントローラーがビューを変更しているかどうかを追跡する必要がある場合もあります。

この特定の例では、解決策は、テキスト フィールド内のテキストが変更されたときではなく、編集が完了したときに、コントローラーにテキスト フィールドからのイベントをリッスンさせることです。

于 2015-01-23T19:27:18.290 に答える
0

Observableパターンでこの問題について聞いたことがないので、そのために+1します。一方で、Java がObserverObservableを介してjava.util パッケージにこのパターンをどのように実装したかを見てみましょう。別の注意として、このパターンの不適切な使用により、この問題が実際のアプリケーションで発生する可能性があることを確認してください。Observer パターンに関する Martin Fowlerのこれらの落とし穴。

于 2013-03-04T01:59:34.137 に答える