Ant is a freelance Java architect and developer. He has been writing a blog and white papers since 2004 and writes about anything he finds interesting, related to Java or software. Most recently he has been working on enterprise systems involving Eclipse RCP, Google GWT, Hibernate, Spring and J2ME. He believes very strongly in being involved in all parts of the software life cycle. Ant is a DZone MVB and is not an employee of DZone and has posted 26 posts at DZone. You can read more from them at their website. View Full User Profile

Choosing a Model/Event Pattern

03.19.2010
| 5143 views |
  • submit to reddit

The following diagrams show different implementation patterns of models and corresponding events, as typically used in the UI. Depending upon your needs, you can use the following tables to decide which pattern to implement.

The patterns are split into model patterns and event patterns. Not all combinations of the patterns make sense, but patterns can be combined to fulfill your unique requirements. At the end I make some recommendations.

Model Pattern 1 - Automatic Event Firing


With the above pattern every change to the model results in an event being fired. Typically if the focus of a text field is lost, the model gets set (in Eclipse RCP perhaps using databinding). Any views that show this model attribute get notified and update themselves. Works well for cases where multiple views of the same model need to be continuously up to date. A big disadvantage is the number of events which get fired. You also need to watch out for cyclic dependencies whereby an event updates a second view, and that update fires another event which updates the first. UI performance can suffer with this pattern, because its granularity is simply too fine.

 

Model Pattern 2 - Manual Event Firing


This pattern lets the caller (typically the controller) fire an event after it has finished updating all parts of the model. Typically the controller performs any validation of multiple fields, may call the server and when everything is good, updates the UI's model. An example might be when an input dialog is closed and the data from that dialog's model needs to be incorporated in one single sweep into the main model. Advantages of this pattern are that events are only fired when all data has been validated together and you can be sure all data is coherent. The disadvantage with this pattern is that you rely on the caller to fire the event (the developer must remember to write that code!). What typically happens is that the same fire method gets called frequently. When implementing this pattern, you can choose if you supply one "fire" method which takes an enumerator, or whether you supply many methods, one for each relevant level of granularity.

 

 

Model Pattern 3 - Coarse Grained Model Methods


In order to reduce the number of events which are fired by Model Pattern 1, and reduce the problems of the caller having to fire events in Model Pattern 2, the above pattern provides coarse grained methods for updating multiple model parts together, in one "transaction". The model implementation sets all the relevant parts based on the given parameters, and only at the end fires a relevant or several relevant events (in the above example, perhaps an event that some elephants were added and an event that some hippos were added).

 

 

Model Pattern 4 - Model with Suspendable Event Firing


A different solution to the disadvantages of Model Patterns 1 & 2, is to allow the caller to suspend event firing temporarily. While this approach is interesting, its comes with dangers like losing events from concurrent model updates. For example, a user event causes a call to update a large amount of attributes. In the mean time, another user event causes a single attribute to be updated, but because event firing has been suspended as part of the first update, its event is never fired. The solution is that when resuming event firing, a generic event is fired, to tell all listeners that the entire model may have changed. While this pattern builds upon Model Patterns 1 & 2, it still suffers like Model Pattern 2, by relying on the caller to make a call to resume event firing at the end. Again, a controller can encapsulate these extra calls for resuming, so that they are at least all located in a logical place.

 

 

Event Pattern 1 - Listener is told about granularity of event


In the above pattern, the listener is given a hint about what has changed. The listener can then base its decision on what to refresh upon this context. Better implementations don't use Strings, rather use an object hierarchy, firstly so that the pattern becomes strongly typed, and secondly so that tests of "implements" can be carried out, so that the listeners implementation does not get filled full of "if" or "switch" statements. For example, a specific listener may be interested when any animal in the zoo is modified, whereby a different listener may be interested in specific events like elephants and hippos changing. With this pattern, the listener must have a reference to the model in order to get the refreshed data and as such may not know that only one item in a list has been changed, causing it to refresh more of the view than necessary, as might be the case with tables where only one row has changed.

 

 

Event Pattern 2 - Listener provides context specific methods


In this pattern, the listener is informed about fine or coarse grained events, but does not get told about say individual rows in a table which have changed, forcing the whole table to be updated. This pattern is also less flexible than Event Pattern 1, because the implementation cannot test for an events superclass. Effectively this pattern is like Event Pattern 1 when using Strings, only it is strongly typed. As such, Event Pattern 1 is more flexible.

 

 

Event Pattern 3 - Listener receives model parts - fine grained


With this pattern the listener is told exactly what has changed, which has the advantage that the listener only needs to update exactly what has changed, for example a single row in a table. This pattern implicitly relies on Model Pattern 1, and is hence fine grained.

 

 

Event Pattern 4 - Listener receives multiple model parts - coarse grained


This pattern extends Event Pattern 3 by becoming capable of handling multiple updates because the listener is given a number of changed items at the same time. It might be associated with Model Pattern 2, 3 or 4, where multiple updates are performed before the event is fired, however as shown, it is constrained because all changes need to be of the same type.

In my experience Model Pattern 3 and Event Pattern 1 are the best combination because they are the most flexible and reduce the number of events being fired which improves performance and usability. In cases where it is important for the view to only update certain rows of a table, the listener methods can be changed to also pass the changed objects to the listener, however this is only required in cases where UI performance would otherwise be really poor.

I would like the thank Mike Moor and Vera Fischer of the SBB for their inputs.

From http://blog.maxant.co.uk

Published at DZone with permission of Ant Kutschera, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Derek Smith replied on Fri, 2010/03/19 - 8:39am

You dont mention an event bus. All of the designs you have listed require hard links between the event publisher and event listener. In more complex systems, it becomes more difficult to support that hard link between the two. An event bus provides even more flexibility by removing the need to maintain the hard link between the publisher and subscriber.

Jose Smith replied on Fri, 2010/03/19 - 10:16am

Good article.  As Derek said I wish it also discussed an event bus or central event dispatcher with pros and cons.  My current project was the first time I was exposed to a central dispatching mechanism.  One of the bigger pains for me in past projects using observer pattern was managing and cleaning up listeners.  I always had some case where a dead view may still be referenced as a listener on a model or a view may accidentally receive the same event from multiple instances of the same model.  Caugh it up to lack of experience or poor design at the time (was just out of college), but so far using a central dispatcher removes much of the pain of doing proper mvc.

A subscriber can simply say "I'm interested in these types of events, A, B, and C.  I don't care where they come from.  When I no longer care about these events, I will unsubscribe myself from the main dispatcher".  So there's only one place where a controller is hooked to the dispatcher.  With the straight observer pattern, a view may be a listener on multiple models and thus is responsible from removing itself from each object.

Now, it hasn't been all roses with our current architecture.  For instance, one issue with our app is if you have a windowed application, and inside the window there's a tree. The tree's view fires a TREE_NODE_CLICKED event which goes through the central dispatcher to all subscribers.  The problem is the developer intended it to be constrained to that Window (or a single instance of a controller - of which there can be multiple).  So while we solved this issue our solution seem less than optimal.  I would imagine there's a common design pattern for this.  It would be cool if this article was expanded to address this.

Ant Kutschera replied on Wed, 2010/03/24 - 5:35am

hi derek and jonathan,

thanks for the comments. to be honest, ive heard of such central dispatchers but never looked at them in detail. do you guys know of any good online references which you could post here?

cheers,

ant

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.