开发者

How to avoid infinite loop in Observer pattern?

I have only one class with many instances. Every instance is observer of couple of other i开发者_JAVA技巧nstances. As well every instance can be observable by couple of another instances.

How to avoid infinite loop of calling update() in observers?


If your system is single threaded, then you simply need a guard inside your notify method:

private boolean _notifying;

public void notify() {
  if(_notifying) {
    return;
  }
  _notifying = true;
  try {
    // ... do notifying here...
  } finally {
    _notifying = false;
  }
}


What you are looking for is a graph-traversal algorithm that detects cycles. One simple approach (that only works in a single threaded scenario) is to keep a global/static counter to let each top-level update() invocation get a unique identifier. Each observer then tracks whether already it has processed the update with the given identifier (ID) and in that case ignores it. This means that your update method will have to be expanded with a parameter with the ID number of the specific update.


Well, if you are defining the "event" object, you could maybe add to it the objects that have processed the event already. In that case, if you close the loop you can exit. In seudo-code

eventFired(Event e)
  if (e.hasBeenEvaluatedBy(this)){
    return;
  }
  e.addEvaluator(this);

  // Do magic

  refire(e);
}

In this case we get something like: * A fires something. * B processes it and adds itself to the list * B refires * C processes event and adds itself to the list * C refires * A processes the event and adds itself to the list * A refires * B catches the event, but is already on the list. No refire, infinite loop broken

Ids could be used instead of pointers to avoid garbage collection issues


Let your observers add received events (or their ids) to some temporary storage and when every new event is received let them verify whether the same event is saved in the storage. If it is then they shouldn't handle it.

But if we'll try to solve a problem rather than find a suitable workaround then: your problem is that object A can listen to object B, and object B can listen to object A at the same time (maybe with some intermediary objects). It's a bad design IMHO.

Observers should be used to loose coupling, making object A know about object B, but not vice versa.

If your objects A and B both know about each other then I don't see why you need to use observers.


One way is to only fire events like updated if something was actually updated. The benefit of this approach is that you can often reduce the number of events triggered (reducing work) and simplify the code. e.g.

final Set<String> set = ...

public void onAdded(String string) {
   // is only added once.
   if (set.add(string)) {
       // only notifies once no matter how many times onAdded is 
       // called for this string, recursively or not.
       notifyAdded(string);
   }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜