Hello, I've read many posts on MVC, but one point still remains unclear. As I understand, general MVC scheme would be smth like this: View --uses--> Model (View fills GUI fields with values from Model) View --notifies--> Controller (user requests some action) Controller --uses--> Model (retrieves data to perform action, performs action) Controller --notifies--> View (passes action results) - maybe this is optional Model --notifies--> View (View updates GUI) The problems is, that I'm not sure about that View - Model relation. If View 'knows' about Model, then why we need Controller? Seems like View uses only some set of Model methods, while Controller uses almost all of them. So here comes my idea - define two interfaces for Model: DataModel - provides methods to access data members, used by View. BusinessModel - extends DataModel with additional business logic (methods like doX(), doY() etc.) used by Controller. Any comments on this? Thanks.
Gytis, Although there are a number of variations of MVC, the single most important point behind MVC is to promote loose coupling by keeping the data Model independent of any View or Views that are using it. In Swing, the ListModel, TableModel, and TreeModel interfaces are used to promote loose coupling between the View and Model and also between the Model and Controller. Classes implementing these interfaces are Mediators that go between the real data source and any Views or Controllers you define. Keeping the Model and Controller separate allows you to more easily vary the implementation of the real data source. Should you decide you need to change out your real data source to a different implementation, you will then have to either refactor out your business logic or worse duplicate it in the new Model. If you are convinced you will not need this flexibility either now or in the future or you would rather pay the price, if there is one, of the separation later, then go for it and combine them.
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
GJ: The problems is, that I'm not sure about that View - Model relation. If View 'knows' about Model, then why we need Controller? Seems like View uses only some set of Model methods, while Controller uses almost all of them. I have a few comments in addition to those offered by Ken. First, the View doesn't need to know anything about the model, except for how to subscribe to the Model (to become its listener). In this implementation, the View has no knowledge of the business methods in the Model. All it is capable of is to receive notifications from the model via a callback method in the View itself. This is refered to as a "push" model (i.e, the model pushes the data doewn to the views). In the pull implementation, the View does know about the Model and can invoke the business methods directly. You may notice that in this implementation the View is already overloaded with the responsibilities. Now, if you add to it the responsibility to react to user's actions and potentially select the other views (which is normally the Controller job), you may end up with a View that does too much. In its purest form the View knows one thing, -- how to render the incoming data in its widgets, and that's all. You may deviate from that purety, but don't loose sight of it, as it is what MVC is all about.
The problems is, that I'm not sure about that View - Model relation. If View 'knows' about Model, then why we need Controller? Seems like View uses only some set of Model methods, while Controller uses almost all of them.
hi,gytis,I have a few comments in addition to those offered by Eugene. first,in the GoF's book,the relation of Model and View is decoupled by the observer pattern.the view only need to know the Model's get***() method. second,in the general MVC,Controller is used to handle the event or to control the flow,it only need to know the Model's set***() method. last,the MVC's basic intent is to let you change views freely without influencing model as ken had posted,so,if without controller,this intent is difficult to reache.
Joined: Feb 02, 2004
Ken, now I see two possibilities to decouple View from Model: 1. use some kind of Mediator (I'm still not sure about those TableModel etc., since they are related to GUI, i.e. TableModel Mediator says, that our View has some king of table inside, so this brings some sort of limitation on View implementation). Maybe I could use some custom class, just a buffer to pass data between Model and View. As Eugene said, this would be 'pull' implementation. 2. use Oberver/Observable pattern - 'push' model by Eugene. But in this case I have no idea how to push 'startup' data into a View - we can not use messages, since our Model was not changed. The only way I was able to figure out is to pass data in Observer registration, i.e.: addObserver(view) ... view.setX view.setY ... But these two solutions still have some kind of coupling between View and Model - we can add/remove properties into/from a Model in 'pull' case without changind Views, the same problem with 'push' - Views still expect to receive set of properties. So I do not see any difference in these two approaches.
Joined: Nov 27, 2002
Gytis, I would reemphasize my first point, in that it is most important to make sure that the Model has no dependency on any View or Views that use it.
1. use some kind of Mediator (I'm still not sure about those TableModel etc., since they are related to GUI, i.e. TableModel Mediator says, that our View has some king of table inside, so this brings some sort of limitation on View implementation).
You seem to be confusing the Model with the real data source. The purpose of TableModel, is to act as a helper for JTable. It ***IS*** part of the gui. Its role is to wrap the real data source and make it easy for JTable to work with. The real data source could be a List or array of some specific type of Object, or it could be some other type of collection, perhaps a set of rows from a relational database.
Maybe I could use some custom class, just a buffer to pass data between Model and View. As Eugene said, this would be 'pull' implementation.
For JTable, the easiest thing is to provide it with an implementation of the TableModel interface. There are at least 4 ways to do this: 1. implement TableModel directly 2. extend AbstractTableModel 3. use a DefaultTableModel 4. extend DefaultTableModel My preference, generally, is option #2 as it is the easiest because it provides simple default implementations for the TableModel methods and also provides convenient methods to fire notifications to its listeners. You only need to override those methods that you need.
2. use Oberver/Observable pattern - 'push' model by Eugene.
Eugene's point is well taken as it is good to be aware of the 2 types for those occasions when you need to roll your own type of notification system. In a simple push model, the event object carries the data and the listener doesn't have to query the data source for it. The View, or its helper, only need to know how to register a listener for change events. An example of this technique is the PropertyChange... classes in the java.beans package. In a simple pull model, the event just signals that a change has occurred and it is the responsibility of the listener to go get the data, which it may do immediately or at some more convenient point in time. In this case, the View, or its helper, has to know more about the Model to get the data. The choices come down to whether your app needs the more heavyweight but simpler push model or the lighter but more complex pull model. There simply is no one right answer to this question. Another choice to make is to roll your own event notification system or just use an existing one. It's ususally easier to do the latter if it will serve your needs without too much trouble. The collaboration between JTable and TableModel is an example of a more complex combination of push and pull. The TableModelEvent carries some information about what changed but the listener has to go get the actual data that changed. JTable takes care of the heavy lifting for you by detecting the changes that were encapsulated in the event and making the appropriate callbacks to the TableModel. This is one aspect of the design of Swing that I really like. Once you understand it, it's really pretty easy to use and flexible to boot. How can you beat that combination ? [ February 03, 2004: Message edited by: Ken Krebs ]