4

I've been reading about MVC a lot recently, because I need to learn how to separate model and GUI for a project in school. (The teacher has said nothing about it, so I'm trying to learn it myself.)

I believe I understand the bacis principles with the view "registering" with the model with actionlisteners, or something along those lines. But I just can't get it into code. I've looked at several small programs, but they are somehow still too big for me to understand the basics.

Could someone please explain it as if explaining to a 5 year old, or give me some links or a really simple example program or something? Thanks a lot!

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
Rickard
  • 1,289
  • 1
  • 17
  • 27
  • 1
    note that you're asking about [GUI MVC](http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller#Implementations_of_MVC_as_GUI_frameworks), which is different to [Web MVC](http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller#Implementations_of_MVC_as_web-based_frameworks). I'd bet most of the answers you'll get will be about the second. – Javier Dec 09 '10 at 22:58
  • @Javier: No worries :) I figured out his question thanks to "actionlisteners". – Goran Jovic Dec 09 '10 at 23:02
  • @Rickard: Be sure to read zengr's answer, too. It will come handy as soon as you ditch Swing and start writing webapps – Goran Jovic Dec 09 '10 at 23:03

3 Answers3

4

Now, the very basic thing about MVC is to separate M, V and C.

On one side you have your classes, and code that does something, like calculate sum of two input numbers, or does something with database, whatever. That's your Model.

On the other side you have some other classes which are responsible for forms, text inputs, buttons and things visible on the screen. That's the View.

Now, Controller is the one linking these two. Usually (in say Swing) you would have your controller implement the Listener interfaces, then you would add the controller as your listener to the screen components you want your software to react on, like buttons. And the implemented handler method wouldn't do anything else except calling whichever method you have implemented in you Model.

I hope this made it more clear..

Goran Jovic
  • 9,418
  • 3
  • 43
  • 75
  • I thought the controller did the calculate sum of two input, and the model held what the two values are. – Steven Dec 09 '10 at 22:56
  • Nope.. That's the whole point. Controller doesn't do anything except "forwarding" stuff.. Both holding values and calculating are typically done in the Model. The "holding value" part is usually called Domain Model, while the "calculating" part is Service Layer. – Goran Jovic Dec 09 '10 at 22:59
  • It did make it clearer, although I still don't understand how to implement the listener from the controller to the model. – Rickard Dec 09 '10 at 23:10
  • There are some examples here: http://life.csu.edu.au/java-tut/uiswing/learn/index.html Just be sure to have a separate class (controller) implement listener interface and then don't add `this` object as a listener but the controller instead. – Goran Jovic Dec 09 '10 at 23:48
  • Be sure to try out the solutions in tutorials yourself. It will be worth the experience even if it isn't fit with theoretical MVC. Remember, in the end programming is in the fingers.. – Goran Jovic Dec 09 '10 at 23:53
4

First, you need to understand the Observer pattern.

The basic idea is that you define an object that notifies interested parties when it changes. (Note that the Observer pattern is a bit more general - Observables notify Observers about "some event". For MVC, that event is "something changed")

First you define a contract between the OBSERVABLE and OBSERVER

package aaa;

// AN OBSERVER INTERFACE
// This is a contract between an interested party (the OBSERVER) and
//   the thing it would like to know has changed (the OBSERVABLE)
// The OBSERVABLE will call this method whenever its data changes
public interface SomethingChangedListener {
    void somethingChanged(String name, Object newValue);
}

Then you define the OBSERVABLE

package aaa;

import java.util.ArrayList;
import java.util.List;

// An OBSERVABLE class
public class Person {
    // STEP 1: keep track of "who cares"
    //         outsiders with interest implement the observer interface
    //         and register with the person to indicate that they care
    private List<SomethingChangedListener> listeners = new ArrayList<SomethingChangedListener>();
    public void addSomethingChangedListener(SomethingChangedListener scl) {
        listeners.add(scl);
    }
    public void removeSomethingChangedListener(SomethingChangedListener scl) {
        listeners.remove(scl);
    }

    // STEP 2: be able to notify those observers by calling a method in the observer interface
    protected void fireSomethingChanged(String name, Object newValue) {
        for (SomethingChangedListener scl : listeners) {
            scl.somethingChanged(name, newValue);
        }
    }

    // STEP 3: whenever the data changes, notify the observers
    private String name;
    private int age;

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
        fireSomethingChanged("age", name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
        fireSomethingChanged("name", name);
    }
}

This allows any other object to "listen" for changes on the thing it's interested in, as long as it implements that observer interface.

For example:

package aaa;

public class Test1 {
    private static class TestObserver implements SomethingChangedListener {
        @Override public void somethingChanged(String name, Object newValue) {
            System.out.println("Property '" + name + "' changed to '" + newValue + "'");
        }
    }
    public static void main(String[] args) {
        Person p = new Person();
        p.addSomethingChangedListener(new TestObserver());
        p.setName("Scott");
        p.setAge(43);
    }
}

Creates an instance of the observable (the Person), registers an observer (TestObserver), and then interacts with the Observable. When run, we see

Property 'name' changed to 'Scott'
Property 'age' changed to 'Scott'

So far so good.

Now let's call the Person our MODEL. The MODEL represents the data that we want to manipulate and view.

We can do this in a "user interface". The user interface can be, but is not limited to:

  • A Graphical User Interface (GUI)
  • A Command-Line Interface (CLI)
  • A Web Application (HTML, JSP, ASP, etc)
  • A Web Service (SOAP, REST, etc)

The code for each of these types of user interfaces (UIs) can be drastically different, but the concepts are the same.

The user interface (UI) allows a user (a person or another computer for example) to see information about the model and make changes to that information.

The "View" is the part of the UI that displays the information for the user. It reads data from the model and formats it in some way to present it.

If the model changes, the View must be updated. To accomplish this, it registers observers with the model. Those observers simply refresh the relevant parts of the presentation in the View.

Now what happens if the user wants to make a change?

We define a "Controller" in the UI as code that interprets user interaction with that UI. For example, if the user types in the "name" field, the controller may interpret that as "change the value of 'name' to the text the user has typed. The controller makes a

person.setName(textFromField);

call to update the model.

Remember what that setName() method does? It notifies the observers of the change. This will cause the UI to update its view.

Note that "view" and "controller" do not need to be separate classes; they're often combined. It's really the roles of "view" (the part of the UI that displays model data) and "controller" (the part of the UI that interprets user interaction and updates the model) that are important to understand.

In some settings, such as Web Applications, the view and controller are very separate. The controller interprets the HTTP requests that are made to the server and updates the mode. The view renders HTML responses to the user. (If you're doing an AJAX application, the design is a bit more similar to a GUI)

The cool thing about the MVC separation (Model vs UI) is that you can add or remove UIs from the Model at any time, and can have multiple UIs on the same model. If data is changed in one UI, all other UIs are updated to reflect the change.

Cool, eh?

Scott Stanchfield
  • 29,742
  • 9
  • 47
  • 65
  • Wow, thanks, now we're talking! But where would the Controller come in? In the UI-class? Or in a seperate class? Or is that up to me? – Rickard Dec 09 '10 at 23:40
  • The "view" and "controller" may or may not be separate classes. Often it's easier to keep them together, and separating them doesn't always allow reuse. (Though in a web MVC setup, they're very separate). – Scott Stanchfield Dec 10 '10 at 00:25
  • If the Person class has got lets say a "House" class, and a "Pet" class, and so on, I'll have to make a list of listeners for every class, right? – Rickard Dec 10 '10 at 11:42
  • It depends... You can set up listeners in the UI for everything in the model, or you can have the Person listen to its constituents and send change messages on their behalf. Or, you can define a higher-level Model class that tracks all of the lower-level model objects and reports their changes. It's one of those "it depends" situations, and I've done it several ways. Note that often it is nice to listen to individual parts so you can have specific sub-UIs to handle specific parts (like a Pet edit window) – Scott Stanchfield Dec 10 '10 at 16:18
2

This diagram might help you to understand the relationship of MVC in Java

UI component is the View, Control servlet (just catch all the incoming requests here and redirect them to the correct business object) is the Controller and the business objects is the Model.

That is my interpretation of MVC in java. Other answers are welcome.

alt text

Community
  • 1
  • 1
zengr
  • 38,346
  • 37
  • 130
  • 192