2

I'm learning the MVC pattern right now and I have a short question concerning models and view. I have the following model:

class Person {
  private String name;
  private int age;
}

Now I want my view to ask some input to create a new Person:

public void askPerson() {
  System.out.println("Enter name:");
  //read with System.in
  System.out.println("Enter age:");
  //read with System.in
}

What is now the correct way to create this model. Should I:

1) save the user input in variables in my view and get them in my controller through getters in order to create the model in the controller (getName(), getAge()) or

2) should I create the model in the view and return it as a result of askPerson()?

What is in general the best way to pass such data from the view to the controller?

Thank you!

freakout
  • 53
  • 1
  • 1
  • 11

2 Answers2

1

The cleanest way is to let controllers listen on the view. In turn the view can tell the controller something needs to happen.

Here is a fully functional example that can be compiled and run

In short it boils down to this.

In this example we assume the controller is already added as an observer to the view.

The view that will notify it's observers (controller).

class CreatePersonView extends Observable implements View {
    public void display() {
        System.out.println("\nWelcome to the create person view!");
        System.out.println("----------------------------------");

        System.out.print("Name: ");
        String name = System.console().readLine().trim();

        System.out.print("Age: ");     
        int age = Integer.valueOf(System.console().readLine().trim());

        Map<String, Object> data = new HashMap<String, Object>();

        data.put("name", name);
        data.put("age", age);

        // generate the event
        setChanged();
        notifyObservers(data);
    }
}

The controller that will consume the event.

class Controller implements Observer {

    PersonService service;

    public void setPersonService(PersonService service) {
        this.service = service;
    }

    // simplified version
    public void update(Observable sender, Object arg) {
        Map data = (Map)arg;
        Person p = service.create((String)data.get("name"), (Integer)data.get("age"));

        //debug
        System.out.println("Created new person: " + p);
    }
}

The main benefit here is that the controller doesn't know anything about the implementation of the view and vice versa. Making them loosely coupled and interchangeable. Which is the whole purpose of MVC.

Bart
  • 17,070
  • 5
  • 61
  • 80
  • @Bart Thank you! This pattern is really easy to understand and seems to work nice. But how would you implement in this example another function, for example if you want to delete a person? The view method gets an ArrayList of Persons and should tell the controller which person to delete. How would you implement this scenario in the given example? – freakout May 26 '13 at 08:08
  • @freakout I know this implementation has the limitation of only triggering the `update` method. If you need something more sophisticated you can add better event handling. I will leave that part to you since it has nothing to do with MVC and you will learn a lot more if you try to figure it out for yourself. You can ask a question again of you find yourself in trouble implementing it. Here's a article to get you going http://en.wikibooks.org/wiki/Java_Programming/Event_Handling. – Bart May 26 '13 at 10:27
0

Create your bean object, fill it and send it from View to Controller. A similar post can give you help to write the code. Here is the link:

MVC sending data from View to Controller

Ok as per your request, let me put some code here. This code is created only for the purpose of your understanding. So modify it as per your need and feel free to make any improvements.

Model class

class MyModel {
      private String name;
      private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "MyModel [name=" + name + ", age=" + age + "]";
    }


}

View Class

class MyView {

/**
 * Create view elements, take user inputs and  
 * set the in the model object. Finally send it
 * to the controller for processing
 */


private void onSomeViewEvent(Object myevent) {
    MyModel model = new MyModel();

    // take the properties from event and set in model
    model.setAge(25);
    model.setName("Yourname");

    // send to controller
    MyController controller = new MyController();
    controller.processRequest(model);
}

}

Controller Class

class MyController {

    public void processRequest(MyModel model) {

        /**
         * Inspect the model and process it as per your need.
         */
    }
}
Community
  • 1
  • 1
Juned Ahsan
  • 67,789
  • 12
  • 98
  • 136
  • Could you provide a small code snippet for my example for better understanding? Thank you! – freakout May 25 '13 at 12:32
  • Thank you, but unfortunately I don't unterstand how this should work. Should I create one view for each model and return the whole view object to the controller? – freakout May 25 '13 at 12:37
  • @freakout Updated resolution to help you with some sample code. – Juned Ahsan May 25 '13 at 12:46
  • Thank you, so it seems to be ok to create the model object in the view. I'm a little bit concerned that the view is to strong tied to the model in this situation. – freakout May 25 '13 at 12:48
  • Model is used to transfer information. There is no problem with that. You are not putting any processing logic in the view, that is handled by the controller. So all the layers are playing their part. If you want you can create a different class to transfer the information and a different class to save the information. But all depends on the need . – Juned Ahsan May 25 '13 at 12:51
  • @JunedAhsan The processing logic should be done in the model/service layer. Not in the controller. The controller is just the bridge between the view and model layer. Also your `MyView` has knowledge of the `MyModel` implementation which is not a good thing. The `MyView` should indeed generate an event which the `MyController` should listen to. The logic is a bit backwards now in your code sample. – Bart May 25 '13 at 15:05