Уведомление наблюдателей от вложенных структур - PullRequest
3 голосов
/ 11 июля 2011

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

Модель данных представлена ​​вложенной структурой:

Model
- Node
  - Leaf
  - Leaf
- Node
  - Leaf

Каждый элемент наследуется от общего абстрактного базового класса (StructuredNode).

Проблема, о которой я думал, заключается в том, что наблюдатели должны иметь возможность подписаться на Модель (и только на Модель), но каждый элемент должен иметь возможность отправлять уведомления об изменениях. Это может быть достигнуто двумя способами - либо уведомления направляются вверх по иерархии, пока они не достигают Модели, где они доставляются к наблюдателям, либо путем реализации уведомлений в базовом классе со статическим списком наблюдателей, как в этом примере:

public abstract class Base {

  private static Map<IObserver> observers;


  protected synchronized void internalSubscribe(final IObserver observer) {
    observers.add(observer);
  }

  protected synchronized void notifyObservers(final Base obj) {
    for (IObserver observer : observers)
      observer.changed(obj);
  }

  // .. other base class operations
}

В этой реализации только Model будет предлагать открытый метод подписки, который внутренне делегирует защищенному методу internalSubscribe базового класса. В то же время каждая производная базового класса может отправлять уведомление об изменении, например:

// Perform some operations that change the object's internal state
// ...
// Then notify all observers
notifyObservers(this);

Это довольно хорошая или скорее плохая практика (с использованием статического списка наблюдателей)? Есть мнения по этому поводу? Есть ли альтернативные решения?

1 Ответ

1 голос
/ 05 августа 2011

Статический список наблюдателей не является распространенным решением, и я не считаю это хорошей практикой для модели общего использования.

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

Конечно, все это может не применяться в вашем случае.Если вы знаете, что в вашем приложении не будет более одной модели этого класса, тогда вы вполне можете использовать это решение.

В любом случае, требование иметь только модель с открытым методом подписки не должноограничить вас использованием контейнера статического наблюдателя для совместного использования всеми экземплярами модели.Как вы сказали, есть другой способ.Маршрутизация уведомлений вверх по иерархии - ИМХО правильный путь.

Если вы хотите избежать маршрутизации, то вы можете выбрать, чтобы узлы сохраняли ссылку на свою модель.Это может быть более эффективным, если вы знаете, что древовидная структура будет глубокой и не очень динамичной.Если узлы могут быть перемещены из одной модели в другую, то это немного рискованно и требует некоторого дополнительного кода для обновления ссылки.

...