Question directed at JamesCherill specifically, (and anyone else who can answer it)

I've never had too much trouble with communicating between the model and the view, in an application that only has a model and a view. However, looking at the observer pattern (at the bottom) of this link, I am somewhat confused. What does it mean for the view to "register a listener with the model"? I thought it meant the pattern that is shown in the example here, but the guy's notes say he hasn't provided an example of it yet, so obviously I am wrong.

Recommended Answers

All 18 Replies

P.S.

The reason for all these questions is because I'm currently doing a project using a three tiered architecture. I know how to make the GUI and the data stay correctly (so that the info on the GUI = info in the model) updated at all times, however, I'm researching these things to find the best way to do this. (i.e., the way that would require the least future maintenance, and the way that best separates the tiers into parts)

Here's the simplest example I can piece together of a listener (which is an observer). You've used it quite a bit in Swing and I'm sure you will recognize the elements immediately

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

public class mainTest {

    public static void main(String[] args) {
        Model model = new Model();
        View view = new View();

        /** add the view as a listener */
        model.addListener(view);

        /** do something to the model */
        model.updateSomething();
    }
}

class Model {
    /** list of interested listeners (observers, same thing) */
    List<ModelListener> listeners = new ArrayList<ModelListener>();

    /** add a new ModelListener observer for this Model */
    public void addListener(ModelListener listener) {
        listeners.add(listener);
    }

    /** called internally when you need to tell the observer stuff changed */
    private void fireStuffChanged() {
        for (ModelListener listener : listeners) {
            listener.stuffChanged();
        }
    }

    /** method that results in a change in the model */
    public void updateSomething() {
        // do whatever
        System.out.println("Model: I'm changin stuff in here...");
        // notify observers
        fireStuffChanged();
    }
}

/** interface for the listeners/observers callback method */
interface ModelListener {

    void stuffChanged();
}

class View implements ModelListener {

    public void stuffChanged() {
        System.out.println("View: Oh, something changed. I better show the new stuff!");
    }
}

You may want to glance through this article as well, which shows a simple pattern of even further separating the observers from the observed with a message queue on a separate thread: http://www.javaworld.com/javaworld/javatips/jw-javatip29.html

It's probably overkill for what you have in mind, but it does present another example of separating the state of one thing from other things that may want to observe and react to that state.

(And it has pictures, which my plain example does not :P )

I understand how your example works, but it seems like that technique works only when you want to update everything in the GUI all at the same time. Lets say I want to modify that code because my GUI has probably 20 windows in total. And lets say that if something in the model is changed which affects a particular window, I want that window to update, but I do not want everything else to update as well. How would I modify your code so that this could work?

Edit:

Well, I guess I could just have something like the following in the Model class:

class Model{
private Dog dog;
private Cat cat;
private Person person;

List<ModelListener> dogListeners= new ArrayList<DogListener>();
List<ModelListener> catListeners = new ArrayList<CatListener>();
List<ModelListener> personListeners = new ArrayList<PersonListener>();


public void addDogListener(DogListener listener) {
dogListeners.add(listener);
}

//Two more methods, one for adding cat listeners and one for person listeners.

public void fireDogsChanged(){
for (DogListener d: dogListeners)
d.stuffChanged();
}

//Two more methods to do the same as above for cats and people.

}

I'd look through the link you provided, but at this point, I'm still wrapping my head around some of the MVC stuff. I understand the basic definition, and what each part (M-V-C) is supposed to do, but the implementations are still difficult for me right now. For example, on those leepoint notes I linked to, where he does an example of MVC with an observer, I understand exactly how he did it. But it doesn't make sense for me to make 100 inner classes and do that for every button I have. And one more question:

Essentially, the difference between the method you showed me in this thread, and the method in the leepoint link I posted, is that in yours, the View responds to a change in the model's data, whereas in the leepoint, the Controller responds to a request by the View that needs the data from the model. Right?

Ezzaral - thanks for your help. I'd still appreciate if you answered or if someone answered the questions I posed above, but I feel like I understand this diagram (the first one) fully now. Hopefully I will still feel that way tomorrow. I'm going to use a pull model for my project (the example you posted was push, I believe).

Hi guys! Just saw this thread and had to join in!
For me, the key issue about separation of GUI and model is about good architecture. Sure, you can hard-code calls to the GUI in the model, and hard-code calls to the model in the GUI, but if you do both you just get one big ball of spaghetti and an inevitable decline into chaos.
IMHO GUI/model separation requires the use of Observer, no choice.
The point is that the model just implements an Observable interface, and has no knowledge of the GUI or anything else that may use it.
You can code, compile, and test, the model without the GUI, then you can safely put it in jar, and get on the the GUI as a separate task.
The project I'm currently doing enhancement work on has one model, but supports three user interfaces (local GUI, remote GUI, web browser). Because it had proper Observer architecture, adding the web browser interface required zero changes to the model or the GUI code. That's enough to convince me.
In response to the specific Q about lots of windows and selective updating: I think you should not try to split the Observable interface into sub-interfaces to meet a GUI requirement; that's just another way to entangle the two layers. Provide an Observable interface that's designed around the model and what can happen within it. Windows, or whatever, can register with the model if they want to know what's happening, but are perfectly free to have empty methods for the events they don't care about (we've ll done this with MouseListener for example)

commented: All good info. +20

Part 2: thoughts on push vs pull.
I think it's a false dichotomy; you have both.
The model will have various public getter methods that a UI can call to get valid current data from the model any time it wants. That's what may probably happen when the window is first opened, for example.
The problem is that the UI won't know if its data becomes out of date, and that's where the Observer pattern kicks in. The listener interface should not attempt to transmit every detail of what's changed; it should give enough info for an Observer to decide if it's interested.
Trivial example:
Model is a Customer class. Public methods getName, getAddress etc etc.
Listener interface could look like this:

interface CustomerListener {
   public void customerChanged(Customer c);
   public void customerAdded(Customer c);
}

Typical code in the UI could look like this:

public void customerChanged(Customer c) {
   if (c != theCustomerImCurrentlyDisplaying) return;
   nameField.setText(c.getName);
   ... 
}

So the fact of an update is pushed to anyone who's interested, but the details are pulled only as and when required.

You may want to glance through this article as well, which shows a simple pattern of even further separating the observers from the observed with a message queue on a separate thread:.
It's probably overkill for what you have in mind...

I agree. But it reminds me of one important point in the Swing environment. The change to the model may well happen on a thread other than the Swing EDT thread (eg some database access or network-based server thing). If the model just calls the listeners, and they go ahead and start doing UI updates (as in my previous trivial example) you have the potential for horrible concurrent access thread bugs - remember that Swing's code is not thread-safe. In my own code I sometimes have to have two ways for a listener to register itself, depending on whether or not it wants to be called back on the Swing thread.

Yes, thanks James, that's a good point to mention on the asynchronous update. It definitely adds some concurrency concerns which need to be weighed against any perceived performance gains.

I should probably clarify that I didn't link the article in a sense of "here's an even better way to do it" so much as here's another example that goes even further - and it has diagrams! :)

@ James: I'm not worried about memory consistency errors. I have a pretty good understanding of that, but I'll keep it in mind. I

edit: I don't really understand your example though, James. you mind explaining further/ providing a short outline of the rest of the classes?

Part 2: thoughts on push vs pull.
I think it's a false dichotomy; you have both.
The model will have various public getter methods that a UI can call to get valid current data from the model any time it wants. That's what may probably happen when the window is first opened, for example.

Me: So if I understand this correctly, you're saying that this is the pull part, but any MVC uses both.

The problem is that the UI won't know if its data becomes out of date, and that's where the Observer pattern kicks in. The listener interface should not attempt to transmit every detail of what's changed; it should give enough info for an Observer to decide if it's interested.

Me: So basically, you're saying that the model should only tell the view that something it wants to know about has changed, but the view is responsible for calling the model's methods in order to retrieve the information it is interested in. (i.e. this would not only mean less work/code for the model, but it would mean more logic separation between the model and the view). Right?

Trivial example:
Model is a Customer class. Public methods getName, getAddress etc etc.
Listener interface could look like this:

interface CustomerListener {
   public void customerChanged(Customer c);
   public void customerAdded(Customer c);
}

Typical code in the UI could look like this:

public void customerChanged(Customer c) {
   if (c != theCustomerImCurrentlyDisplaying) return;
   nameField.setText(c.getName);
   ... 
}

Your code example that you provided here. . would it be implemented the same way Ezzaral's example was? I'm assuming so, since they are both Observer patterns. If so, how would it be implemented with a Controller? Ezzaral's example only used a model and a view. I'm curious how it'd work with all three as separate parts.

... how would it be implemented with a Controller? Ezzaral's example only used a model and a view. I'm curious how it'd work with all three as separate parts.

I'mo going to come clean here: I don't think that separation of the controller and the view works well in a typical Swing app, and I personally rarely do it. The controller needs so much access to the fields in the view that the code is far simpler when they are in the same class.
Where a controller becomes useful IMHO is when you have a complex model consisting of a number of elements. In that case you would use a controller to organise them all - eg you may have an app for purchasing an item. The model layer may involve: items, warehouse stock, customer details, pricing and discounts, delivery methods etc, so it would make sense to have a controller that called on all those elements in turn to complete the overall process.

The answers to your other 3 questions are: Yes, Yes, Yes.

Let me know if you still want a bit more flesh on the trivial example.

I'mo going to come clean here: I don't think that separation of the controller and the view works well in a typical Swing app, and I personally rarely do it. The controller needs so much access to the fields in the view that the code is far simpler when they are in the same class.

I agree. It's pretty much just model and view in most cases.

In response to the specific Q about lots of windows and selective updating: I think you should not try to split the Observable interface into sub-interfaces to meet a GUI requirement; that's just another way to entangle the two layers. Provide an Observable interface that's designed around the model and what can happen within it. Windows, or whatever, can register with the model if they want to know what's happening, but are perfectly free to have empty methods for the events they don't care about (we've ll done this with MouseListener for example)

Good point about further entangling the two layers. The thing is, there is one Object that all of the GUI windows (that ever need to be changed) show information about. The Object is a Patient, and the Patient has these categories in the model: Medical Information, General Information, Emergency Contact Information, etc. The GUI has one window for displaying each of these categories. So I don't see why there couldn't be a list of Listeners (in the model), one per category. Or would it be better to just set it up like Ezzaral said, with only one list of Listeners, and in the GUI, the stuffChanged method would decide which windows needed to be updated?

Thanks

Also, my project technically has to use a three tiered architecture. That's why I was interested in doing it with MVC. Although the two are different, they are much more similar than (MV)-C. Technically, communicating using listeners between the view and the model would be cheating, since they are not supposed to communicate between each other at all.

... So I don't see why there couldn't be a list of Listeners (in the model), one per category. Or would it be better to just set it up like Ezzaral said, with only one list of Listeners, and in the GUI, the stuffChanged method would decide which windows needed to be updated?

I think there's no one right answer here. As long as the Listeners are defined in terms of what's in the model, rather than what's in the GUI, you should go for whatever gives the cleanest easiest to understand implementation for your particular case.

As for 3-layer, you can always take all the response handling code out into a separate class, and hey-presto there's your controller (!).
But... when people talk about "3 tier architecture" they more usually mean user interface / business model & logic / data storage & persistence. So in your example the third layer would be the (so far unmentioned) database or whatever the patient info is stored in. I guess you have to take the context of your course to see what applies here.

Well, in our case, for the three tier architecture, we have:

GUI -- Application Layer (interacts between GUI & Model) -- Model (Patient classes & methods)

Which seems to be somewhat different than what you are saying. Of course, we do not have anything significant for data storage, since we are just using serializable.

>I think there's no one right answer here.
Bingo.
This is the point where design becomes more art than science and you don't really have a set of rules laid out for you. You try to encapsulate functionality and decouple responsibility as best you can given the specifics of your subsystems and requirements. Managing that complexity effectively becomes a career.

commented: Well said, and very true. +29
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.