Model View Controller paradigm
Hello -- I'm trying to get some practice with the model-view-controller design pattern for programming, and I want to make sure that I understand it correctly. The whole point of MVC is that each aspect of the program (model, view, controller) is seperated completely and cleanly from the other aspects so that one can be changed easily without affecting the other two. What I'm unsure of with this, though, is how the three pieces interact and communicate with each other when you do. The only solution to this question that I have figured out is to pass each object to the other two and have them store the reference as part of the class.
class model
{
controller l;
}
class view
{
controller l;
}
class controller
{
model m;
view v;
}
Is this the "correct" way to accomplish this? Or is there an easier/better way?
Ihave coded up a mine sweeper-ish type program using MVC with the style example above and it *works*, but that doesn't mean that it's what's actually used in the industry. Please let me know if that's correct or if it's done differently.
[1414 byte] By [
JJCoolBa] at [2007-11-27 2:10:31]

Check out this recent thread for a discussion of this: http://forum.java.sun.com/thread.jspa?threadID=5164529
[url #" style="display: block; background-image: url('http://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/ModelViewControllerDiagram.svg/321px-ModelViewControllerDiagram.svg.png'); width:321px; height: 151px] [/url]
Description:
A simple diagram depicting the relationship between the Model, View, and Controller. Note: the solid lines indicate a direct association, and the dashed line indicate an indirect association (e.g., observer pattern).
Often, the model maintains a collection of view objects, not just one.
Another diagram:[url #" style="display: block; background-image: url(' http://java.sun.com/developer/technicalArticles/javase/mvc/images/Figure1.gif'); width: 550px; height: 385px] [/url]From this article: http://java.sun.com/developer/technicalArticles/javase/mvc/
> Check out this recent thread for a discussion of
> this:
> http://forum.java.sun.com/thread.jspa?threadID=5164529
[quote]Yes. And in fact in the proper MVC model, the controller has references to both view and model, but the view has only reference to the model.[/quote]
That's what I've done above.. Apart from giving the view access to the model. (In my mine sweeper program, the controller variable in my view class was ONLY used to register actionListeners on my components) However, the controller (since it's mine sweeper) is the object that's updating the text on the buttons.. I guess technically that's incorrect. But, at least, I can say that the following is more correct than what I listed first?
class model
{
}
class view
{
model m;
}
class controller
{
model m;
view v;
}
Will the model ever need a reference to the controller? A correctly designed controller should pretty much have only event listeners inside of it, yes? If that's the case, I don't see a situation when the model would ever need to directly call some method of the controller.
I think you can segregate MVC layers by introducing three seprate layers:
Model:
Provide some code which access a database and does something with it,push or pull data.
getData(){// data accessing code}
Controller/Business Object:
Provide method(s) which works as a wrapper to access DB(Model) layer
getPurchaseOrderList(){
//access method of Model layer
}
View:
viewPurchaseOrderInDataGrid(){
//access method from Controller layer
}
Here you see, all code units are seperate from each other and can me modified without affecting one another.This is a very simple example to implement a MVC design pattern.I hope it helps.
I hope , you would like to explore for more upcomin things beyond design patterns :
http://planetjavajee.blogspot.com/
Do send in your comments and suggestions..
Happy learning..
One more thing: there an obverser pattern relationship between the model and the views, so the model will have a reference to the view, and often a collection.
http://en.wikipedia.org/wiki/Observer_pattern
In fact, many people save MVC isn't really a pattern, but an aggregate, or dog pile, of patterns.
> Another diagram:
> From this article:
> http://java.sun.com/developer/technicalArticles/javase
> /mvc/
I appreciate the diagrams, Dr, but I've seen them already and, unfortunately, while they describe the associations visually (which is part of my current understanding), they don't quite explain how it actually works out in code. :( Which is why I'm asking about that aspect of it.. But ... the 2nd diagram you have there suggests that the solid arrows mean that the object has to have a direct reference to the place it points to (as in, controller has a model and a view that it knows about, and the view has a model that it knows about).. Which is what I posted just above this.. So that's helpful also. But also in the 2nd diagram, it shows an event arrow going from the model to the view.. That would mean that the view listens to changes in the model .... how would you accomplish this? Would I need to write methods inside my model that created/threw (?) events?
I'll post my (granted messy) mine sweeper program so you can point out which parts I probably coded incorrectly. (If you have time/don't mind)
it's 202 lines long..
import java.util.Random;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
public class minesweep
{
public static void main(String[] args)
{
controller l = new controller();
view app = new view(20,15,l);
model game = new model(20,15,l);
l.setView(app);
l.setModel(game);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}
/**
The model for a minesweeper game
*/
class model
{
boolean[][] grid;
int mines;
ActionListener l;
public model(int w, int h, ActionListener list)
{
l = list;
grid = new boolean[w][h];
mines = w*h/3;
placeMines();
}
/**
A method to place the mines onto the grid.
It is only used by the constructor.
*/
private void placeMines()
{
for (int i = 0; i < grid.length; i++)
for (int j = 0; j < grid[i].length; j++)
grid[i][j] = false;
Random rand = new Random();
int x, y;
boolean flag;
for (int i = 0; i < mines; i++)
{
flag = false;
while (!flag)
{
x = rand.nextInt(grid.length);
y = rand.nextInt(grid[x].length);
if (grid[x][y] == false)
{
grid[x][y] = true;
flag = true;
}
}
}
}
/**
A method to determine if there's a bomb on a square or not.
@param x the x value to check.
@param y the y value to check.
*/
public boolean isBomb(int x, int y)
{
boolean val;
try
{
val = grid[x][y];
}
catch (ArrayIndexOutOfBoundsException e)
{
val = false;
}
return val;
}
/**
A method to report how many bombs are around a square
@param x the x value to check.
@param y the y value to check.
*/
public int reportBomb(int x, int y)
{
int n = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
try
{
if (i == 0 && j == 0) ;
else if (grid[x + i][y + j] == true)
n++;
}
catch (ArrayIndexOutOfBoundsException e)
{
}
}
}
return n;
}
}
/**
The view for a minesweeper game
*/
class view extends JFrame
{
JPanel p;
ActionListener l;
public view(int x, int y, ActionListener list)
{
super();
l = list;
p = new JPanel();
p.setLayout(new GridLayout(y,x));
for (int h = 0; h < y; h++)
{
for (int w = 0; w < x; w++)
{
p.add(new mineButton(w, h, l));
}
}
this.getContentPane().add(p);
pack();
setResizable(false);
}
}
/**
The controller for a minesweeper game
*/
class controller implements ActionListener
{
model data;
view GUI;
public void actionPerformed(ActionEvent e)
{
mineButton src = (mineButton) e.getSource();
if (data.isBomb(src.getX(), src.getY()))
{
}
else
{
src.setText(String.valueOf(data.reportBomb(src.getX(), src.getY())));
}
src.setEnabled(false);
}
public void setModel(model m)
{
data = m;
}
public void setView(view v)
{
GUI = v;
}
}
/**
A button used for the game
*/
class mineButton extends JButton
{
int x;
int y;
public mineButton(int w, int h, ActionListener l)
{
super();
x = w;
y = h;
addActionListener(l);
setPreferredSize(new Dimension(15,15));
setMargin(new Insets(0,0,0,0));
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
> That would mean that the view listens to changes in the model ....
> how would you accomplish this? Would I need to write methods inside my
> model that created/threw (?) events?
(The prefered buzzword is raised: the model raises events.)
This model-view relationship is the classic observer pattern I mentioned
a couple posts ago. As an example of coding it, check out the initial discussion
in the class javax.swing.event.EventListenerList:
http://java.sun.com/javase/6/docs/api/javax/swing/event/EventListenerList.html
Also, that other thread is getting into the details of how GUI events get from the view to the controller: http://forum.java.sun.com/thread.jspa?threadID=5164529
> (The prefered buzzword is raised: the model
> raises events.)
*blush* hehe
> Also, that other thread is getting into the details
> of how GUI events get from the view to the
> controller:
> http://forum.java.sun.com/thread.jspa?threadID=5164529
That's one issue that I feel comfortable with for the most part. GUI event generating is pretty straight forward to understand.. But a model (where there is only data and methods to access/modify data) causing events with no visual interaction of a component listening to something is less straight forward.. XD Anyway -- which "other thread" are you referring to? The one Hunter posted initially? Or the one you posted initially? (I've already looked at Hunters, but I won't have time to check yours out until after work today)
edit: n/m .. didn't see you added the thread link there.
So .... in my mine sweeper program.. If I were to have my "reportMine" method send an event to the view to update the display of the mineButton (as opposed to the controller doing it directly) ... that would be closer to the correct way to code it under MVC?
As far as the model raising events: it's a clean way to keep the model loosely coupled to the view.
Don't think of events (event raising and handling) as just a GUI feature.
It's a completely general paradigm, and one that a lot of code would
benefit from, if used more widely (and wisely).
> So .... in my mine sweeper program.. If I were to
> have my "reportMine" method send an event to the view
> to update the display of the mineButton (as opposed
> to the controller doing it directly) ... that would
> be closer to the correct way to code it under MVC?
I haven't had a chance to review your code, but that sounds right.
Usually the controller doesn't change the view to reflect state change in
the model. Instead, the model raises events to notify the view. This is because,
sometimes you have multiple views and a controller may not be aware of all of them.
A simple example of multiple views would be if your minesweeper had a split screen
to help display a large board, or you created a ScoreBoard as a simple view
to just display the current score.
> As far as the model raising events: it's a clean way
> to keep the model loosely coupled to the view.
> Don't think of events (event raising and handling) as
> just a GUI feature.
> It's a completely general paradigm, and one that a
> lot of code would
> benefit from, if used more widely (and wisely).
*nods* My point was simply that having a GUI in front of you makes event raising more conceptually understandable. ^.^ Could you provide me with a (simple) method that would raise an event that's NOT associated to a component? I understand the concept, just not the implementation.
> Could you provide me with a (simple) method that would raise an event
> that's NOT associated to a component? I understand
> the concept, just not the implementation.
Your model could raise a ModelStateChange event when its state is changed.
Your model could have a EventListenerList field and then the code involved
would be a simple copy-paste-edit of what is described in that class.
> Your model could raise a ModelStateChange event when its state is changed.
> Your model could have a EventListenerList field and then the code involved
> would be a simple copy-paste-edit of what is described in that class.
Ok .. I think I see what you're referring to in the EventListenerList on the API. Slightly confusing for now, but I'll read it closely and think about it and try a sample program to see if I can get it.. But I *don't* see a "ModelStateChange" event in the API.. I imagine that would be an event object that I coded myself?
class modelStateChangeEvent extends AWTEvent (?)
{
// my event code
}
yes/no?
BTW - I'm gonna give you 8 dukes, Dr, and I'll give Hunter 2 for the help on this when I get off work today also.
Hang on, I'll whip up a quick example...
Here is the example. It mainly shows how to use EventListenerList.
import java.util.*;
import javax.swing.event.*;
interface ModelListener extends EventListener {
public void modelStateChanged(ModelChangedEvent evt);
}
class ModelChangedEvent extends EventObject {
private static final long serialVersionUID = 0;
public ModelChangedEvent(Model source) {
super(source);
}
public Model getModel() {
return (Model) getSource();
}
}
class Model {
private EventListenerList ll = new EventListenerList();
private ModelChangedEvent modelEvent = new ModelChangedEvent(this);
public void addModelListener(ModelListener l) {
ll.add(ModelListener.class, l);
}
public void removeModelListener(ModelListener l) {
ll.remove(ModelListener.class, l);
}
protected void fireModelChangedEvent() {
Object[] listeners = ll.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ModelListener.class) {
((ModelListener)listeners[i+1]).modelStateChanged(modelEvent);
}
}
}
private int sampleState;
public int getSampleState() {
return sampleState;
}
public void setSampleState(int newState) {
sampleState = newState;
fireModelChangedEvent();
}
}
class SampleModelListener implements ModelListener {
public void modelStateChanged(ModelChangedEvent evt) {
System.out.println("SampleModelListener sees new state of " + evt.getModel().getSampleState());
}
}
public class ModelExample {
public static void main(String[] args) {
ModelListener l = new SampleModelListener();
Model m = new Model();
m.addModelListener(l);
//do some state changes
m.setSampleState(10);
m.setSampleState(9);
m.setSampleState(8);
}
}
ok Thanks Dr. I will check it out (yet again) when I'm off work today. I appreciate it greatly. I was also wondering if there might be any way I could get contact info from you? (If you don't mind if I shoot you an email or something from time to time about this stuff) No worries if you aren't comfortable with that.
I'm always lurking here. And there's lots of smart people here, so just throw it out into the forum...
protected void fireModelChangedEvent() {
Object[] listeners = ll.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ModelListener.class) {
((ModelListener)listeners[i+1]).modelStateChanged(modelEvent);
}
}
}
I haven't looked at the EventListenerList class closely yet, but this implies that it stores objects and events in pairs? The list contains an object and the next entry in the list contains which type of event the object is registered for? So the length of the list will always be an even number? Or is that backwards? *looks at it again*
> I haven't looked at the EventListenerList class closely yet, but this implies that it stores objects and events in pairs?
That's right. It stores: class, listener, class, listener, ...class, listener.
> So the length of the list will always be an even number?
Yes.
The reason why it does this is so that you can store different listeners in the same
instance of EventListenerList, so that one doesn't have to instantiate this class
many times because a component maintains lists of ComponentListeners,
ActionListeners, KeyListeners, etc...
One more question..
public void addModelListener(ModelListener l) {
ll.add(ModelListener.class, l);
}
I'm not too familiar with the <interface>.class notation being used here.. Is the <interface>.class a reference to the class that is implementing the interface? If that's the case, what is being stored into the list? Not a reference to an instance of a class, but just the class definition itself? Which aspect of the class?
>>The reason why it does this is so that you can store different listeners in the same
>>instance of EventListenerList, so that one doesn't have to instantiate this class
>>many times because a component maintains lists of ComponentListeners,
>>ActionListeners, KeyListeners, etc...
*nod* That's sorta what I figured. ^.^
> I'm not too familiar with the <interface>.class
> notation being used here.. Is the <interface>.class
> a reference to the class that is implementing the
> interface?
No, ModelListener.class refers to the java.lang.Class object associated
with interface ModelListener. Perhaps they should have used the syntax
ModelListener.type, but they didn't...
> If that's the case, what is being stored
> into the list? Not a reference to an instance of a
> class, but just the class definition itself? Which
> aspect of the class?
Associated with every type (including every class and interface) is an
instance of java.lang.Class. This class is useful in reflection, but that's
not why its used here. It's used so that the EventListenerList can
simultaneously maintain several different listeners lists. Suppose you
want your class to maintain a list of ActionListeners and a list of
FocusListeners. A single EventListenerList can do that by storing pairs:
either ActionListener.class and an action listener, or FocusListener.class
and a focus listener. Now suppose your class X implements both
ActionListener and FocusListener, but you add it only as a FocusListener.
This guarantees that if you are raising an action event, you will not invoke
X's actionPerformed method, even though it is an ActionListener, and it
is on the EventListenerList.
What about the Observer interface and Observable class provided by java.util? I posted a question about it in the other thread?
> What about the Observer interface and Observable class provided by java.util?
You can use java.util. Observer/Observable, too, but there's nothing
special about them. If you open up src.zip you'll realize there's not
a lot to them, and I don't think they're used anywhere else that I've seen
in the API.
I guess I'm partial to EventListenerList, but there's nothing remarkable about it
either. It has a certain amount of thread safety to it, if that matters...
In the end, it wouldn't be hard to roll up your own code to support the observer
pattern directly, either.
ok. Thanks Dr! You've been very helpful! ^.^ I'll start another application and try to incorporate this into it. I'll probably be back this weekend with more questions.
When using the Observer/Observable method, how would I get the view to pull the initial data from the model?
Edit: I have found a simple way of doing it. Overriding the addObserver(Observer o) method and fowarding the call to the superclass but also adding a setChanged() and a notifyObservers() call to the method. Everytime a new observer is added (such as when a view is created) the data is automatically sent to the view.
public void addObserver(Observer o) {
super.addObserver(o);
setChanged();
notifyObservers();
}
... or you could get the view to pull the initial data from the model in the view's setModel method:
public void setModel(Model model) {
this.model = model;
...pull !...
}
What would you do for the update() method (when using an observer) in your case to avoid repeating the code that populates the field?
You could *push* information about the change in the model. If you are using
java.util.Observer:
public void update(Observable o, Object arg) {
MyHint hint = (MyHint) arg;
... use information in hint...
}
Usually, to just get something up and running, I don't get that fancy. Just
have the view assume nothing and start from scratch. You can also
write slicker code later.