Il n'y a pas de directives de conception communément acceptées (c'est-à-dire de facto ) pour MVC. Ce n'est pas si difficile que ça de le faire vous-même, mais cela nécessite une certaine planification de vos cours et beaucoup de temps et de patience.
La raison pour laquelle il n'y a pas de solution définitive est qu'il existe plusieurs façons de faire du MVC, toutes avec leurs avantages et leurs inconvénients. Soyez donc intelligent et faites ce qui vous convient le mieux.
Pour répondre à votre question, vous souhaitez également dissocier le contrôleur de la vue (vous pouvez donc utiliser la même logique de règle métier pour une application Swing et dans l'application console). Dans l'exemple Swing, vous voulez découpler le contrôleur du JWindow
widget et de n'importe quel widget dans Swing. La façon dont je le faisais (avant d'utiliser les cadres réels) consiste à créer une interface pour la vue que le contrôleur utilise:
public interface PersonView {
void setPersons(Collection<Person> persons);
}
public class PersonController {
private PersonView view;
private PersonModel model;
public PersonController(PersonView view, PersonModel model) {
this.view = view;
this.model = model;
}
// ... methods to affect the model etc.
// such as refreshing and sort:
public void refresh() {
this.view.setPersons(model.getAsList());
}
public void sortByName(boolean descending) {
// do your sorting through the model.
this.view.setPersons(model.getSortedByName());
}
}
Pour cette solution lors du démarrage, vous devez enregistrer le contrôleur dans la vue.
public class PersonWindow extends JWindow implements PersonView {
PersonController controller;
Model model;
// ... Constructor etc.
public void initialize() {
this.controller = new PersonController(this, this.model);
// do all the other swing stuff
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// TODO: set the JList (in case that's you are using)
// to use the given parameter
}
}
Ce pourrait être une bonne idée de créer un conteneur IoC pour faire toute la configuration pour vous à la place.
Quoi qu'il en soit, de cette façon, vous pouvez implémenter des vues console uniquement, en utilisant les mêmes contrôleurs:
public class PersonConsole implements PersonView {
PersonController controller;
Model model;
public static void main(String[] args) {
new PersonConsole().run();
}
public void run() {
this.model = createModel();
this.controller = new PersonController(this, this.model);
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// just output the collection to the console
StringBuffer output = new StringBuffer();
for(Person p : persons) {
output.append(String.format("%s%n", p.getName()));
}
System.out.println(output);
}
public void createModel() {
// TODO: create this.model
}
// this could be expanded with simple console menu with keyboard
// input and other console specific stuff
}
La partie amusante est de savoir comment gérer les événements. J'ai implémenté cela en laissant la vue s'enregistrer auprès du contrôleur à l'aide d'une interface, cela se fait en utilisant le modèle Observer (si vous utilisez .NET, vous utiliseriez des gestionnaires d'événements à la place). Voici un exemple d'un simple "observateur de documents", qui signale quand un document a été enregistré ou chargé.
public interface DocumentObserver {
void onDocumentSave(DocModel saved);
void onDocumentLoad(DocModel loaded);
}
// in your controller you implement register/unregister methods
private List<DocumentObserver> observers;
// register observer in to the controller
public void addObserver(DocumentObserver o) {
this.observers.add(o);
}
// unregisters observer from the controller
public void removeObserver(DocumentObserver o) {
this.observers.remove(o);
}
public saveDoc() {
DocModel model = model.save();
for (DocumentObserver o : observers) {
o.onDocumentSave(model);
}
}
public loadDoc(String path) {
DocModel model = model.load(path);
for (DocumentObserver o : observers) {
o.onDocumentLoad(model);
}
}
De cette façon, la vue peut se mettre à jour correctement car elle s'abonne aux mises à jour du document. Il suffit de mettre en œuvre l' DocumentObserver
interface:
public class DocumentWindow extends JWindow
implements DocView, DocumentObserver {
//... all swing stuff
public void onDocumentSave(DocModel saved) {
// No-op
}
public void onDocumentLoad(DocModel loaded) {
// do what you need with the loaded model to the
// swing components, or let the controller do it on
// the view interface
}
// ...
}
J'espère que ces exemples motivants vous donneront quelques idées sur la façon de le faire vous-même. Cependant, je vous conseille fortement d'envisager d'utiliser des frameworks en Java qui font la plupart des choses pour vous, sinon vous finirez par avoir beaucoup de code standard qui prend beaucoup de temps à écrire. Il existe quelques plates-formes client enrichi (RCP) que vous pouvez utiliser pour implémenter certaines des fonctionnalités de base dont vous avez le plus probablement besoin, telles que la gestion des documents à l'échelle de l'application et une grande quantité de gestion des événements de base.
Il y a un couple auquel je peux penser de ma tête: Eclipse et Netbeans RCP.
Vous devez encore développer des contrôleurs et des modèles pour vous-même, mais c'est pourquoi vous utilisez un ORM. L'exemple serait Hibernate .
Les conteneurs IoC sont cool'n all, mais il existe également des cadres pour cela. Tels que Spring (qui gère également les données entre autres).