4

複数のタイプのイベントをオブザーバーに通知するオブザーバブルの update() 呼び出しを解釈するときに、関連する醜い条件付きキャストを回避しようとしています。また、フラグを notifyObservers()/update() メソッドに渡したくないです。

オブザーバーが監視可能なオブジェクトをポーリングして変更内容を確認する必要はありません。この新しいデータを update() メソッド (または同様のもの) を介してオブザーバーに提供したいと考えています。

私には解決策のアイデアがあります。通知の種類ごとに 1 つの監視可能なオブジェクトをインスタンス化します。例: オブザーバブルはハードウェア デバイスを表すオブジェクトであり、その状態を表すオブザーバブルが含まれます。

public final Observable connectionState = new Observable();
public final Observable dataState = new Observable ();

このように、オブザーバーは、1 つのオブザーバー、つまり通知タイプごとに 1 つのオーバーライドされた update() メソッドを使用できるため、クエリや条件付きキャストを行う必要はありません。

多くの欲求不満の後、これは私が考えることができる最もエレガントな解決策ですが、オブザーバー/オブザーバブルを適切に使用する方法についてのポイントを逃したという恐ろしい気持ちがあります。

そのソリューションに関する私の主な問題は次のとおりです。

  1. まだキャストが含まれています(少なくとも条件付きではありません)
  2. オブザーバブルはオブザーバブルである必要があるため、パブリック メンバーである必要があります。これにより、オブザーバーは addObservable() を呼び出すことができますが、notifyObservers() を呼び出すこともできます。

私は正しいことをしていますか?

ありがとう

4

3 に答える 3

4

あなたはオブザーバーパターンのJava1.0実装の制限に苦しんでいます。java.util.Observableはどこでも使用されていますか?という質問に対するこの回答を見てください。

それらの設計には欠陥があるため、使用されていません。タイプセーフではありません。Observerを実装する任意のオブジェクトを任意のObservableにアタッチできます。これにより、将来的に微妙なバグが発生する可能性があります。

タイプセーフなインターフェース内にそれらをラップすることは、パターンを最初から実装するのとほぼ同じ量の作業であるため、ほとんどの場合、後者が好ましいと思います。

要件をjava.util.Observerに詰め込もうとするのではなく、ニーズにより適した独自のバージョンのパターンを実装する必要があるかもしれません。

于 2011-07-07T09:32:00.083 に答える
3

ObservableをVisitorパターンと組み合わせて使用​​してみることができます。

class MyObserver implements Observer, EventVisitor {
    public void update(Observable o, Object arg) {
        ((EventAcceptor) arg).accept(this);
    }

    public void visit(SomeEvent v) {
        System.out.println("SomeEvent: " + v.s);
    }

    public void visit(AnotherEvent v) {
        System.out.println("AnotherEvent: " + v.info);
    }
}

interface EventVisitor {
    void visit(SomeEvent v);
    void visit(AnotherEvent v);
}

interface EventAcceptor {
    void accept(EventVisitor v);
}

class SomeEvent implements EventAcceptor {
    public final String s;

    public SomeEvent(String s) {
        this.s = s;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class AnotherEvent implements EventAcceptor {
    public final String info;

    public AnotherEvent(String info) {
        this.info = info;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class MyObservable extends Observable {
    void handleSomeEvent() {
        setChanged();
        notifyObservers(new SomeEvent("some event"));
    }

    void handleAnotherEvent() {
        setChanged();
        notifyObservers(new AnotherEvent("some event"));
    }
}

class Sample {
      public static void main(String[] args) {
          MyObservable observable = new MyObservable();
          observable.addObserver(new MyObserver());
          observable.handleSomeEvent();
          observable.handleAnotherEvent();
      }
}
于 2011-07-07T09:41:55.577 に答える
0

あなたの問題に対して可能な解決策はたくさんあります。Observableクラスが問題に適していない場合は、独自のリスナーのコレクションを維持できます。

interface Listener {
    void onEvent1(Type1 arg);
    void onEvent2(Type2 t2, Type3 t3);
    void onEvent3();
}

List<Listener> listeners = new CopyOnWriteArray<Listener>();

public void addListener(Listener l) { listeners.add(l); }

public void onEvent1(Type1 arg) {
     for(Listener l: listeners) l.onEvent1(arg);
}
于 2011-07-07T09:56:38.210 に答える