user838590
user838590

Reputation:

Notifying observers from nested structures

Currently, I am trying to dissect some tight coupling between the data model and the UI in an application by introducing the MVC pattern. Basically, this means making the model aware of the associated views in order to have them informed whenever properties inside the model change.

The data model is represented by a nested structure:

Model
- Node
  - Leaf
  - Leaf
- Node
  - Leaf

Each element inherits from a common abstract base class (StructuredNode).

The problem I've been thinking about is: observers should be able to subscribe to the Model (and only the Model), but each element should be able to emit change notifications. This could be achieved in two ways - either notifications are routed up the hierarchy until they reach the Model, where they get pushed to the observers, or by implementing notifications in the base class, with a static observers list, as in this example:

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
}

In this implementation, only Model would offer a public subscribe method, which internally would delegate to the protected internalSubscribe method of the base class. At the same time, each derivative of the base class could send a change notification, like this:

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

Is this rather good or rather bad practice (using a static observers list)? Any opinions on this? Are there alternative solutions?

Upvotes: 3

Views: 452

Answers (1)

Frazz
Frazz

Reputation: 3043

A static observer list is not a common solution, and I would not consider it a good practice for a generic use model.

Observers would be notified of changes to models they are not interested in. This means that all the burden of identifying the model firing the notification falls on the observers, which probably have no good and efficient way of doing it other than going up the hierarchy and finding the root node... a lot of code, that must potentially be implemented several times in several observers. In the end it would be simpler for the observer to ignore considerations and just update or recalc, even when the updated model is not the one it's interested in.

Of course all this may not apply in your case. If you know you will not have more than one model of this class in your application, then you can very well go with this solution.

Anyway, the requirement of having only the Model with a public subscribe method should not constrain you to using a static observer container to share among all Model instances. As you said, there is another way. Routing the notifications up the hierarchy is IMHO the correct way to go.

If you want to avoid routing, then you could choose to have the nodes keep a reference to their model. This may be more efficient if you know the tree structure will be deep an not very dynamic. If nodes can be moved from one Model to another, than this is a bit risky and requires some further code to keep the reference updated.

Upvotes: 1

Related Questions