Несколько наблюдаемых событий для одного наблюдаемого - PullRequest
3 голосов
/ 07 июля 2011

Я пытаюсь обойти уродливое условное приведение, используемое при интерпретации вызова update () для наблюдаемой, которая захочет уведомить своих наблюдателей о множественных типах событий. Кроме того, я бы предпочел не передавать флаги методу notifyObservers () / update ().

Я не хочу, чтобы наблюдатели опрашивали наблюдаемый объект, чтобы выяснить, что изменилось, я бы хотел, чтобы эти новые данные передавались наблюдателям через метод update () (или аналогичный.)

У меня есть идея для решения. Я создаю один наблюдаемый объект для каждого типа уведомлений. Например: Observable - это объект, представляющий аппаратное устройство, он будет содержать observables, представляющий его состояние:

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

Таким образом, наблюдателям не нужно выполнять какие-либо запросы или условное приведение, так как один тип наблюдателя, то есть один переопределенный метод update (), может использоваться для каждого типа уведомления.

После большого разочарования это самое элегантное решение, которое я могу себе представить, однако у меня возникло ужасное ощущение, что я упустил момент о том, как правильно использовать Наблюдатели / Наблюдаемые.

Мои основные проблемы с этим решением:

  1. Это все еще включает в себя приведение (по крайней мере, это не условно)
  2. Поскольку наблюдаемые должны быть наблюдаемыми, они должны быть публичными членами. Хотя это позволяет наблюдателям вызывать addObservable (), оно также позволяет им вызывать notifyObservers ().

Я правильно поступаю?

Спасибо

Ответы [ 3 ]

3 голосов
/ 07 июля 2011

Вы можете попробовать использовать 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();
      }
}
3 голосов
/ 07 июля 2011

Вы боретесь с ограничениями реализации Java 1.0 шаблона Observer. Посмотрите на этот ответ на вопрос Используется ли java.util.Observable где-нибудь?

Они не используются, потому что их дизайн ущербен: они не тип безопасный. Вы можете прикрепить любой объект, который реализует Observer для любого Observable, что может привести к тонким ошибкам линия.

Заворачивание их в сейф Интерфейс примерно столько же работать как реализация шаблона из ну, так что я думаю, что последний предпочтительнее в большинстве случаев.

Вместо того, чтобы пытаться включить ваши требования в java.util.Observer, возможно, вам следует просто реализовать собственную версию шаблона, которая лучше соответствует вашим потребностям.

0 голосов
/ 07 июля 2011

Существует множество возможных решений вашей проблемы. Если вы чувствуете, что класс 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...