Question

In my application, I have a scenario where if a change occurs on a particular module, it has to be notified to few other modules. I thought an observer pattern would fit here, by keeping the module on which the change will occur as subject and the modules to be notified as observers.

But going by the principle of observer pattern, the observers are independent of each other. There should be no connection between the observers. In my case, though the modules are different, they are dependent. The successful completion of execution of the first module is important for the next module to execute. Also if the module x fails, all changes made by module 1 to module x-1 has to be reverted. That is, either all the modules has to successfully execute or we have to rollback to previous state. You can imagine it like a transaction. Then I realized I was wrong that observer pattern is not the right way to implement this.

I am kind of stuck up here to come up with a clean design, where there are set of modules who needs to handled when a change in subject happens, but with the constraint the modules are dependent on each other. Can someone help me with this problem to come up with a good design?

Was it helpful?

Solution

You can still use the observer pattern: All you need to do is change the way the event travels across the observers.

In the original design, module X raised and event to module A, B and C. But the problem is that C depends on B, and since you don't control the order (and don't want to) of execution of the observers, you have a problem. I would suggest you simply make C and observer of B, instead of an observer on A!

This way, when A raises the event, it will propagate in the desired order. A -> B -> C.

That being said, I wonder whether you really require this level of decoupling. Basically you are describing here a standard flow of information and unless the modules are very reusable, you can make the calls explicitly. A directly calls B, which directly calls C.

Transactions are an orthogonal concern to data propagation. I am afraid you will have to treat them separately. If you elaborate about the state transitions that potentially need to be rolled back, the community may try to help there too.

OTHER TIPS

About the transaction part. Actually, your problem is that you are executing a sequence of update operations on a db and the failure of one should revert all the previous.

The naive solution would be to simply wrap the originating call in a transaction scope.

begin transaction A: update db Raise event B: update db Raise event C: update db end transaction.

This will probably work! The only problem is that if you have computations in between that prolong the duration of the transaction. Transactions should be as short as possible, thus you need to make sure you don not 'waste' any time during the transaction on actions that do not concern the resource under transaction.

If you have the above problem, you can accumulate all the update commands in a single place (a list of lambda expressions, each wrapping a delayed execution to the db) and run them as soon as all the changes are accumulated.

You could use Composite and an acquire-execute-release structure for your observer. Not sure I would call it observer anymore though - it's more like an abstraction of a transaction combined with composite.

The interface would be something like this:

public interface TransIf {
  boolean acquire();
  void execute() throws TransFailed;
  void release();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top