MVC and its derived design patterns always have the "10 people would find 12 ways to implement it" issue, so I would briefly point out a few "popular" implementations.
So far, what remains common is that your "User Interface" definitely maps to "View" in MVVM. Then it gets a little debatable from here on.
ViewModel is the brain
One popular way to implement MVVM is that the the "ViewModel" is the brain of the whole application. In this case, "Application" maps to "ViewModel" and "Domain" kind of maps to "Model." The ViewModel controls (and decides) what and how to get the data, and also what and how it wants to expose to the View. Most of the time "Model" is just a plain POJO class (e.g. IceCream
class).
For JavaFX, you would let all properties in the Model and ViewModel be represented by some kind of Property
implementation (i.e. something that implements that interface). If you are not using API like "mvvmFX", then most likely your View would have properties bound to other properties in the ViewModel. If you are using "mvvmFX" (which I didn't use), then you would (most likely) be binding View properties to ViewModel via the property name (which is what WPF does).
In this approach, ViewModel is responsible to get the list of ice creams. IceCreamService
could be considered a separate Service
layer, or you could assume that it's part of the ViewModel (it itself isn't a ViewModel but it belongs to ViewModel). If you want to update this list, ViewModel is the one who decides that.
Model as the Domain
Another implementation is make the Model do data management, pretty much like what hibernate does in Spring. Model classes continue to represent data (or entities etc), but it comes with own persistence logic. This means that if you update value of a Model object (e.g. changes flavor of an IceCream
instance), the Model would know that it is "dirty", and would push the change to the repository for example.
MVCVM
I also read of another approach. In short, it is similar to the first approach, but it moves IceCreamService
class into a brand new layer called "Controller."
Your example
Based on your example, this is the sample illustrating how it could be implemented in JavaFX.
class IceCreamSelectionView { // The FXML controller class used as MVVM View class
@FXML ComboBox<String> iceCreams;
@FXML ComboBox<String> flavors;
private final IceCreamSelectionViewModel vm; // The corresponding ViewModel
@FXML private void initialize() {
Bindings.bindContent(iceCreams.getItems(), vm.getIceCreams());
Bindings.bindContent(flavors.getItems(), vm.getFlavors());
vm.selectedIceCreamProperty().bind(iceCreams.valueProperty());
vm.selectedFlavorProperty().bind(flavors.valueProperty());
}
}
class IceCreamSelectionViewModel {
/*
* The properties
*/
public final ObservableList<String> getIceCreams() { return iceCreams; }
public final ObservableList<String> getFlavors() { return flavors; }
public final StringProperty selectedIceCreamProperty() { return selectedIceCream; }
public final StringProperty selectedFlavorProperty() { return selectedFlavor; }
private updateIceCreams() {
iceCreams.setAll(iceCreamService.getIceCreams());
}
}
// There is no Model class because both "iceCream" and "flavor" cannot be further broken down.