Es gibt keine allgemein vereinbarten (dh defacto ) Designrichtlinien für MVC. Es ist nicht ganz so schwer, es selbst zu tun, erfordert aber etwas Planung für Ihren Unterricht und viel Zeit und Geduld.
Der Grund, warum es keine definitive Lösung gibt, ist, dass es mehrere Möglichkeiten gibt, MVC durchzuführen, alle mit ihren Vor- und Nachteilen. Seien Sie also schlau und tun Sie, was am besten zu Ihnen passt.
Um Ihre Frage zu beantworten, möchten Sie den Controller auch von der Ansicht entkoppeln (sodass Sie dieselbe Geschäftsregellogik sowohl für eine Swing-App als auch für die Konsolen-App verwenden können). Im Swing-Beispiel möchten Sie den Controller vom JWindow
Widget und jedem anderen Widget in Swing entkoppeln . Früher habe ich (vor der Verwendung der tatsächlichen Frameworks) eine Schnittstelle für die Ansicht erstellt, die der Controller verwendet:
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());
}
}
Für diese Lösung müssen Sie beim Start den Controller in der Ansicht registrieren.
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
}
}
Es könnte eine gute Idee sein, einen IoC-Container zu erstellen, um stattdessen das gesamte Setup für Sie durchzuführen.
Auf diese Weise können Sie jedoch nur Konsolenansichten mit denselben Controllern implementieren:
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
}
Der lustige Teil ist, wie man Event-Handling macht. Ich habe dies implementiert, indem ich die Ansicht über eine Schnittstelle beim Controller registrieren ließ. Dies erfolgt mithilfe des Observer-Musters (wenn Sie .NET verwenden, verwenden Sie stattdessen Ereignishandler). Hier ist ein Beispiel eines einfachen "Dokumentbeobachters", der signalisiert, wann ein Dokument gespeichert oder geladen wurde.
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);
}
}
Auf diese Weise kann sich die Ansicht ordnungsgemäß selbst aktualisieren, da sie die Dokumentaktualisierungen abonniert. Alles was es tun muss, ist die DocumentObserver
Schnittstelle zu implementieren :
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
}
// ...
}
Ich hoffe, diese motivierenden Beispiele geben Ihnen einige Ideen, wie Sie es selbst machen können. Ich rate Ihnen jedoch dringend, die Verwendung von Frameworks in Java in Betracht zu ziehen, die die meisten Dinge für Sie erledigen, da Sie sonst viel Boilerplate-Code haben, dessen Schreiben lange dauert. Es gibt einige Rich Client Platforms (RCP), die Sie verwenden können, um einige der grundlegenden Funktionen zu implementieren, die Sie höchstwahrscheinlich benötigen, z. B. die anwendungsweite Dokumentenbehandlung und viele grundlegende Ereignisbehandlungen.
Es gibt ein paar, die ich mir vorstellen kann: Eclipse und Netbeans RCPs.
Sie müssen noch Controller und Modelle für sich selbst entwickeln, aber deshalb verwenden Sie ein ORM. Beispiel wäre Ruhezustand .
IoC-Container sind cool, aber es gibt auch Frameworks dafür. Zum Beispiel Spring (das unter anderem auch das Datenhandling übernimmt).