How to avoid endless loop in observer pattern?

I have only one class with many instances. Each instance is an observer of several other instances. Also, each instance can be observed by several other instances.

How to avoid endless loop of update () call in observers?

+4
java design-patterns
source share
5 answers

What you are looking for is a graph traversal algorithm that defines loops. One simple approach (which only works in a single-threaded scenario) is to keep a global / static counter so that each top-level call to update() gets a unique identifier. Then each observer monitors whether he processed the update with the given identifier (ID) and in this case ignores it. This means that your update method must be extended with a parameter with the identifier number of the specific update.

+4
source share

If your system is single-threaded, you just need a protector inside your notification method:

 private boolean _notifying; public void notify() { if(_notifying) { return; } _notifying = true; try { // ... do notifying here... } finally { _notifying = false; } } 
+6
source share

Well, if you define an event object, you can add objects to it that have already processed the event. In this 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: * And something works. * B processes it and adds itself to the list * B refires * C processes the 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 in the list. No refire, endless loop broken

Identifiers can be used instead of pointers to avoid garbage collection problems.

+4
source share

Let your observers add the received events (or their identifiers) to some temporary storage, and when each new event is received, let them check whether the same event is stored in the storage. If so, they should not process it.

But if we try to solve the problem, and not find a suitable solution, then your problem is that object A can listen to object B, and object B can listen to object A at the same time (possibly with some intermediary objects). This is a bad design IMHO.

Observers should be used to loosen traction, making object A aware of object B, but not vice versa.

If your objects A and B both know about each other, I don’t understand why you need to use observers.

+2
source share

One way is to only trigger events such as updated if something is really updated. The advantage of this approach is that you can often reduce the number of triggered events (job reduction) and simplify the code. eg.

 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
source share

All Articles