Reputation: 412
During development process of an Android app I have come across this design puzzle I am not able to solve at the moment. I would appreciate any thoughts, workaround or clean solution :) I ll try to simplify it as much as possible:
Everything starts with a common observer pattern implementation. There is a subject which changes states upon its public method invokations; and there are observers which react accordingly to these changes. In this case, the subject is a STATEFUL subject, which means it has an internal state controller (an int) which changes like an automaton. Each time its state changes it notifies the observers as usual:
But now think of this situation:
What is going to happen now, as a result of the SECOND waterfall, is that next observers(let's say observerB) is gonna receive its notification as state Y (from this last second waterfall), act accordingly and when this SECOND waterfall finishes, the PC (program counter) is gonna continue with the FIRST notification waterfall and renotify to observerB the OLD STATE X. This generates two main issues: first one the observerB gets notified of the new states in wrong order (first state Y and then state X when it should be the opposite way) and second and most important, even being notified in wrong order, when the observerB receives the notification of the new state X it is totally WRONG as the subject real state is Y; and this generates a lot of issues.
As you might have realized, this happens when an observer commits a change in the state of the subject, when it gets notified instead of only gettind data from the subject. I would appreciate any other pattern or solution. Also to clarify there is only one thread.
Thanks in advance.
Upvotes: 1
Views: 648
Reputation: 412
After many hours wondering, I think I have found a possible solution.It has to do with what Thoms Kilian proposes. The key is some kind of post method which queues those methods which change the state of the subject. One possible implementation would be to use a handler and post those methods to the main thread (remember there are no more threads):
client -> subject.anyMethod() //changes subject state to state X
subject -> handler.post(anyMethod())
//nothing to do, so post is executed
subject -> notifyObservers(X) // subject FIRST notification waterfall
observerA -> subject.anyMethod() //changes subject to state Y
//here comes the change
subject -> handler.post(anyMethod())
//pc keeps sending rest of notifications before executing the posted runnable and the second waterfall
This way all observers would access to the same state when changed and queue future events :)
Upvotes: 2
Reputation: 36305
What you need is some kind of semaphore that synchronizes state propagation. When subject
propagates the state change it first sets a semaphore that will lock out any further states changes (or simply propagation of state changes) of subject
. This could also be realized with a stack inside the observer pattern of subject
. Only after all clients have been informed about the state change the semaphore is freed. This way sending of state changes is guaranteed to arrive at all clients in the order they were performed on subject
.
If you model the above with a state machine you would use a history state machine.
Upvotes: 2