M(MVC)C
The world knows about MVC already, of course. In the Java Swing world, I've found this pattern takes on a consistent variation that probably deserves recognition.
In this variation the model component is not a native Swing model. Instead an adapter complex of objects is used to present the backing model using native Swing model interfaces, such as TreeModel, ListModel, etc.
I've found that if you use a pure OOD approach to designing your domain classes, you of course end up with data entity classes which do not use Swing interfaces. You end up with what I call a data model.
Later on, when placing some kind of GUI facade on to the data model so that it can be viewed and/or updated by the user, you create an adapter using native Swing model interfaces. I use the term view model to differentiate this adapter from the data model.
The system of objects ends up looking like 2 MVC complexes, where the view MVC complex plays the role of the data "view", and the data model and a data controller listen and react to this "view". So I call this pattern M(MVC)C. (See illustration.)
There are a couple other consistent features to this pattern:
-
The data model is often multi-threaded, especially in distributed applications. When distributed clients are supposed to "see" each other's updates in their own local data model, the data model needs to be multi-threaded and have (non-Swing) event delivery threads.
-
The view model must deal with the multi-threaded data model, since Swing GUI models are single-threaded -- using the Swing Event thread for both modification and even delivery. Whenever it receives notification from the backing data model, the view model schedules all work to be performed on the Swing Event Thread as soon as possible.
-
The view controller sends commands to the backing data controller. The view model is not updated by the view or view controller directly, but only as a reaction to notifications from the backing data model. (Alternatively, the view model doesn't cache any state, and instead always consults the backing data model when it needs data.)
- Both the data model and the view model are pretty "dumb" and passive, relying on controller objects to implement business rules. The view controller implements GUI-specific business rules. The data controller implements non-GUI business rules associated with the data model.
In J2EE "Fat Clients"
Specifically in J2EE clients, this pattern is actually quite easy to implement. You use JMS messages to distribute server-side data change notifications. On the client-side a data model object represents servers-side state, and typically will cache state as well (to avoid unnecessarty round-trips back to the server). The JMS messages indicate the the data model when its cache is out-of-synch with the server.
Using the JMS event nodification threads means the data model doesn't have to do any thread management at all. The data model will have to do its own thread management for event notification if it must use a "pull" model to get server notifications. See illustration.
In J2EE Servlets
If clients are HTML, then there is a final tier of servlets used to present the data to the clients. A similar pattern may be employed in this environment, though of course you are no longer using native Swing models (necessarily) as view models. Instead you may have some hand-crafted way of organizing cached data in the application scope, session scope or request scope.
You may use the exact same data model code in this setup that you used in the "fat" client. The data model is created/initialized as part of web app intitialization, and a ref to the data model is stored in application scope. Individual presentation view models of the data, which are designed to be condusive to HTML rendering, are stored in session scope, backed by the data model. See illustration.
8:09:51 AM
|