Шаблон наблюдателя с двумя списками наблюдателей


У меня есть класс MyObserver, который слушает изменения в Notifier. Notifier расширяет Observable и уведомляет о своих событиях с помощью notifyObservers (Object). Объект, передаваемый в качестве аргумента, всегда является экземпляром одного и того же класса. Проблема в том, что каждый наблюдатель должен прислушиваться к различным событиям. Например, один наблюдатель должен слушать изменения состояния событий, а другие - все типы событий. Как я могу сделать это с шаблоном наблюдателя?

Спасибо.

4 4

4 ответа:

Если вы можете немного изменить дизайн:

interface MyObserver {
    public void stateChangeEvent();
    public void otherEvent();
}

class MyObserverAdapter implements MyObserver {
    public void stateChangeEvent() {
         // some default implementation or no implementation.
    }

    public void otherEvent() {
         // some default implementation or no implementation.
    }
}

class MyStateChangeObserver extends MyObserverAdapter {
    public void stateChangeEvent() {
         // implement behavior specific to this class.
    }
}

class MyOtherObserver extends MyObserverAdapter {
    public void otherEvent() {
         // implement behavior specific to this class.
    }
}

Использование:

MyObserver stateObserver = new MyStateChangeObserver();
MyObserver otherObserver = new MyOtherObserver();
notifier.notifyObservers(stateObserver);
notifier.notifyObservers(otherObserver);

Используйте notifyObservers(Object arg) version и создайте какой-то объект "типа события", чтобы вставить его туда. В ваших наблюдающих классах просто фильтруйте по переданному в событии классу.

public void update(Object observable, Object arg) {
    if ( (MyEvent) arg.isEventX() ) { /* do stuff */ }
}

Я думаю, что встроенная в Java реализация шаблона Observer не подходит для вашего случая.

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

Итак, в этом случае вам нужно расширить общую модель наблюдателя , определив свой собственный наблюдаемый интерфейс, например, таким образом:

public enum EventKind {
   EVENT_A, EVENT_B, EVENT_C;
}

public interface Observable {
   public void registerObserver(EventKind eventKind);
   public void unregisterObserver(EventKind eventKind);
   public void notifyObservers(EventKind eventKind);
}

Тогда вы можете просто реализуйте этот наблюдаемый интерфейс с внутренними списками для каждого типа событий для уведомления. Вы все еще можете использовать встроенный в Java интерфейс наблюдателя, если хотите.

Этот подход имеет следующие преимущества:

  1. вы можете гибко добавлять больше видов событий не затрагивая код самого Наблюдатели.
  2. вы можете зарегистрировать любого наблюдателя в любой событие.
  3. вы обновляете только наблюдателей которые эффективно заинтересованы в каждый событие.
  4. вы избегаете "пустых методов", "проверки типа события" и других трюки со стороны наблюдателей.

Вы можете проверить изменение состояния, выполнив следующие действия в классе Observable:

public void update(Observable o, Object arg)
{
    if(o.hasChanged())
    {
        // do something
    }
}
Наблюдатели, которые слушают что-либо, не нуждаются в этом тесте. Это, вероятно, самый простой способ, если вы хотите только слушать изменения состояния.