Atul
Atul

Reputation: 1774

Swing MVC - Event Propogation and Data Sharing

I am trying to apply MVC pattern in swing application. However I am facing two major issues given that you have nested hierarchy of panel e.g. Parent -> Child - > Grand Child -> Grand Grand Child.

Issue 1: How to transfer the data between controller and view when you have such a hierarchy? If I go and pass data from parent to child then there will be lots of duplication and if I change one child all the parents will require change. I don't want views to directly access data from db and I want the data to be transferred to views through controller only.

Issue 2: How to propagate the events from view to controller in such a hierarchy? I am thinking of using PropertyChangeListener. View will firePropertyChange event if any action has to be taken by controller. Controller will listen for these events and perform some action. But again if I do this for hierarchy then there will be code duplication.

I have three ideas that could be useful:

  1. To use controller for each Panel but this in this way I will end up with lots of controllers.
  2. Use Mediator design pattern that will provide the communication between views and controller.
  3. Use a Central Reciever & Notifier that will listen for all property change event from views and will notify controllers who are interested. but this will only solve my second issue:

Please refer to below diagram to have a picture of 3rd idea. In case of 2nd one, Mediator will come in center.

Please evaluate and let me know if anyone has implemented such issue in a better way.

enter image description here

Upvotes: 7

Views: 756

Answers (3)

Vishal Shukla
Vishal Shukla

Reputation: 2998

I was facing similar issue when I ended up using this HMVC Pattern. Yes you are right in the sense that there will be lots of controller. But it is also true that it will provide you clear separation of concerns in the code. You can limit number of controllers by creating some application specific, high-level composite widgets. In this case, hierarchy can be limited upto 2 or 3 level at max and controllers can be chained to delegate events to any of the parent/child.

Once you load the data from server, you could also maintain Session map to get some relief to have quick and easy access to frequently required data - however I don't favor it much.

The pattern works quite well if the developments team understands and follows it properly.

Upvotes: 1

James P.
James P.

Reputation: 19617

Issue 1: How to transfer the data between controller and view when you have such a hierarchy? If I go and pass data from parent to child then there will be lots of duplication and if I change one child all the parents will require change. I don't want views to directly access data from db and I want the data to be transferred to views through controller only.

How about ignoring the hierarchy and going for a more linear approach by registering views with a relevant controller ? The data could be had through a model from where changes would be triggered through an Observer or Listener pattern.

With this you won't have any duplication occurring. Everything would be centralized in a model or a series of models. The controller, or controllers could run a notify on a list of registered views after a user action or outside event has occured.

Also, views should definitely not access the data source as you say. There should be at least one layer of abstraction here. If your controller uses the mediator pattern what I'd do is handle this by forwarding requests to an interface in an extra data layer.

Thinking further, I don't think if it would be a good idea to have registration done through the view. So I'd keep this separate. Initialize views by hand or find a way to iterate through views that you need. Perhaps get your views through a kind of factory which automate this step.

Issue 2: How to propagate the events from view to controller in such a hierarchy? I am thinking of using PropertyChangeListener. View will firePropertyChange event if any action has to be taken by controller. Controller will listen for these events and perform some action. But again if I do this for hierarchy then there will be code duplication.

Again, you could adopt a linear approach. When a view is registered the Controller could add it's listeners to it. Or you could have the view send some semantic style messages (ex: doAction("Save")) which can be handled through a dispatch mechanism. Will leave you to decide how parameters could be forwarded.

Would PropertyChangeListeners be needed ? I mean, do you need that kind of granularity ?

I have three ideas that could be useful:

To use controller for each Panel but this in this way I will end up with lots of controllers. Use Mediator design pattern that will provide the communication between views and controller. Use a Central Reciever & Notifier that will listen for all property change event from views and will notify controllers who are interested. but this will only solve my second issue:

This sounds vaguely like HMVC. With this approach you have triads of model-view-controller for each subsystem. It's an interesting idea but could be messy and it's not clear how the hierarchy is supposed to work out and how coordination/subordination is achieved.

Perhaps you could have a fourth neutral class for each module/subsystem of your app where you could plug in a view, model and controller with an Exception thrown if one of them is missing or incorrect.

Or, following this idea of a central notifier, you could have a central Controller acting as a routing mechanism to other feature-specific controllers or more elementary actions. How a message is rerouted to these is up to you. Watch out for threading as centralization will make the design of this class essential.

Whatever you do, try to make things as simple as possible. You should be able to have a test view with model and controller up without too much fuss.

Upvotes: 1

Tiago B
Tiago B

Reputation: 2065

I have a suggestion for your issue 1:

You can have a ViewModel that contains a property of another View Model. And on your controller method you just need to receive the parent ViewModel because the model binder will bind all properties for you.

public class GrandChildViewModel{
    public Int32 SelectedDropDownItem { get; set; }
    public List<Foo> ListOfFoo { get; set; }
}

public class ChildViewModel{
    public String Name { get; set; }
    public Int32 Age { get; set; }
}
public class FatherViewModel{
    public ChildViewModel Child { get; set; }
    public GrandChildViewModel GrandChild { get; set; }
}

This is an example of the hierarchy. Your View will reference FatherViewModel only. And your controllers will receive FatherViewModel also. The modelBinder will automatic do its job, if you create the HTML like:

@Html.TextBoxFor(m => m.Child.Name)

It will render the input:

<input type="text" id="Child_Name" name="Child_Name" />

Upvotes: 1

Related Questions