MVC in Swing (role of controller?)
I have always written my Swing GUI stuff in the abbreviated (model)<-->(view/controller) pattern that you see in the Sun tutorials but have recently been thinking about moving to a proper MVC pattern. I must be misunderstanding the nature of MVC though, because even after reading about it in a few different places on the web I cannot figure out what the controller is supposed to be besides a glorified method forwarder.
Imagine I have a very simple application. It has a JFrame with a single button in it that brings up a JFileChooser. You can select a data file which contains a single integer value. When you do so this value is stored in the model and a message is sent to the view telling it that the model has been updated. The view then changes the title of the JFrame to the integer value.
Can someone walk me down the flow of control starting with when the user clicks the button and point out at each step which part (model, view, or controller) is active?
Drake
[1005 byte] By [
Drake_Duna] at [2007-10-2 11:00:22]

First, the user clicks the button. The controller (typically, an ActionListener implementing the Command Pattern) does its job; no interaction with the model is needed here. Just open the JFileChooser, take its return value and forward it to the model. The model is then in charge of opening the file, reading it and update itself with the value it's read. Since the model implements Observable (or something like that), the Observer (IOW, the view, or at least the part of the view that has an interest in this particular part of the model) gets notified of the model's changes and updates itself accordingly.
That's how I would do it. I don't claim it's the best solution ever, but that's generally how I use MVC.
I see what you mean with "glorified method forwarder"... I suppose it's the "cost" for loose-coupling...
Torajirou has outlined what I consider to be an excellent MVC architecture with maximum decoupling between the relevant tiers. An excellent way to go.
If you want a slightly simpler architecture with more coupling (not generally desired from a design perspective, but usually much quicker to code until the complexity warrants decoupling further):
> User clicks button (view component)
> ActionListener (controller component) invokes model functionality
> Model functionality ... functions ... (vague because this is what makes your app unique)
> ActionListener (controller compoent) receives model results (if any)
> ActionListener (controller component) dispatches to same view or a different view, optionally passing model data to that view
So, what you have is the following:
Controller dependent on model and view
Model dependent on nothing (this is central to the pattern. The model stands on its own. This especially helps with test-driven-development)
View dependent on the model (somewhat on the controller)
What falls out from the above is that it is hard to truly dis-entangle the view and controller. Sometimes MVC as implemented in Swing is simply called Model-Delegate (with Delegate being a mish-mosh of view and controller).
What Torajirou has done by implementing Observer-Observable is to decouple the controller and model more fully. Though, IMO, a dependency still exists. The Command pattern, generally, is used for decoupling. The controller is responsible for creating and populating a Command via user request. This is passed to the model, which uses the request parameters to invoke functionality and optionally store a result in the Command object. The controller then inspects the model result in the Command object (dispatching to the same or a different view) and sends it to the appropriate View. That View may or may not use the Model data in the Command. The View is rendered and the scope of the request ends.
Using the Command pattern will result in the loosest coupling between the tiers. However, there is still coupling between a given tier and a given Command object.
- Saish
Thanks, guys. I am starting to get the picture, but I have some follow-up questions.
About the part where the JFileChooser gets fired up, and referring to Torajirou's design. Could you be more specific about how this happens? The JFileChooser is presumably a part of the view, so does the controller (ActionListener) actually actively command the view to do things?
About the line between the view and controller and the line between Swing and non-Swing. I notice that in both of your designs the controller is an ActionListener. Doesn't that defeat the point of separating the view and controller? Suppose that I decide to write a second view for the application based on JSP instead of Swing. Do I write a JSP view that fires Swing events?
What I was sort of picturing when I asked the question was this:
User clicks button, resulting in fired AWT/Swing event.
View hears its own event and opens JFileChooser.
Once user selects file, view fires abstract (non-SWT/Swing) event.
Controller hears abstract event, and tells model to load up file.
Model loads up file and fires event indicating that its state has changed.
View hears event fired by model and querries model for value, then updates the title bar.
In this vision, the controller reacts to the view, the model reacts to the controller, and the view reacts to the model, forming a nice circle. This is my current (mistaken?) understanding of MVC. However, if I do it this way I am back to scratching my head as to why the controller rises to the level of a separate component. On the other hand, if the controller is listening to Swing events like in the patterns you guys described, I cannot see the point of separating it from the view. So what actual advantage is obtained by having a view and controller instead of a delegate?
Drake
And to follow up on THAT, I did some reading on the Command pattern and it sounds very nice indeed. Roughly speaking how would you implement a Command pattern for the application I described (button click adds one to number displayed on title bar)?Drake
> Thanks, guys. I am starting to get the picture, but
> I have some follow-up questions.
>
> About the part where the JFileChooser gets fired up,
> and referring to Torajirou's design. Could you be
> more specific about how this happens? The
> JFileChooser is presumably a part of the view, so
> does the controller (ActionListener) actually
> actively command the view to do things?
>
It typically passes either a Command object and/or a model object to the view. This can be done via a setXXX() method or a constructor. Your view needs to be coded to render or refresh itself in response to these events.
> About the line between the view and controller and
> the line between Swing and non-Swing. I notice that
> in both of your designs the controller is an
> ActionListener. Doesn't that defeat the point of
> separating the view and controller? Suppose that I
> decide to write a second view for the application
> based on JSP instead of Swing. Do I write a JSP view
> that fires Swing events?
>
See above. Separating the controller and view is difficult. :^)
What you can do is refactor common controller functionality (such as session scope across requests or workflow processing) in actual Java controller classes. Then, Swing or Struts controllers can delegate the workflow to the abstract superclass or helper. Thus, you will have a 'generic' controller for a given request (this could easily be an interface representing a given Command) but specific sub-types for each of your view types. This level of complexity is only justified if you will in fact have two different view types for a given request.
Generally, your listeners are simple controllers. As complexity increases, you can write dedicated controller or Command objects. Additng additional view types means refactoring the controller into generic and specialized controller types.
> What I was sort of picturing when I asked the
> question was this:
>
> User clicks button, resulting in fired AWT/Swing
> event.
> View hears its own event and opens JFileChooser.
> Once user selects file, view fires abstract
> (non-SWT/Swing) event.
> Controller hears abstract event, and tells model to
> load up file.
> Model loads up file and fires event indicating that
> its state has changed.
> View hears event fired by model and querries model
> for value, then updates the title bar.
>
Sounds good.
> In this vision, the controller reacts to the view,
> the model reacts to the controller, and the view
> reacts to the model, forming a nice circle. This is
> my current (mistaken?) understanding of MVC.
> However, if I do it this way I am back to scratching
> g my head as to why the controller rises to the level
> of a separate component. On the other hand, if the
> controller is listening to Swing events like in the
> patterns you guys described, I cannot see the point
> of separating it from the view. So what actual
> advantage is obtained by having a view and controller
> instead of a delegate?
>
Almost right. The view can be thought of as initiating the process. Though personally, I simply like to think of it generically as a user initiating a request. The flow should come back to the controller (though there are design patterns that form a circle as you indicated).
User request
Controller invokes model functionality
Model result returned to controller
Controller dispatches model result to appropriate view
View uses model data to render
User receives response
> Drake
- Saish
> And to follow up on THAT, I did some reading on the
> Command pattern and it sounds very nice indeed.
> Roughly speaking how would you implement a Command
> d pattern for the application I described (button
> click adds one to number displayed on title bar)?
>
> Drake
in this situation, the Command Pattern ensures you don't end up with a global ActionListener that looks like :
if (event.getSource.equals(button1) {
// blah
} else if (event.getSource.equals(button2) {
// blah2
} // and so on
you create a Command for each action, ensuring that when the action gets fired, the right command gets invoked without needing to branch all over the place
Interfaces and polymorphism. Live it, love it. :^)- Saish