Sunday, April 1, 2012

MVC nice article with Observable pattern

4 down vote accepted
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?

No comments:

Post a Comment