Tutorial: Model-View-Controller (MVC) Struktur in Java Projekten nutzen
Die MVC-Architektur erfreut sich in letzter Zeit sehr hoher Beliebtheit, ständig hört man über neue Frameworks die auf diese Architektur schwören. (Beispiele: Spring Framework, ASP.NET MVC, Objective C...)
Bild 1: Der Aufbau - Quelle: Wikipedia
Doch was steckt eigentlich dahinter und warum sollte man seine Struktur überdenken?
Ich denke jeder, der eine Anwendung geschrieben hat schon die Erfahrungen gemacht, dass der Code immer unübersichtlicher wird, je größer ein Projekt wird.
Hier setzt MVC an, denn durch die strickte Teilung von Präsentation (View), der Programmlogik (Controller) und der Datenschicht (Model) erhöht sich die Lesbarkeit und Wartbarkeit des Codes. So kann man ein Projekt viel einfacher um weitere Funktionen ergänzen ohne den halben Sourcecode durchzugucken.
In diesem Artikel möchte ich diese Architektur an einem kleinem Java Beispiel demostrieren. Das Programm ist natürlich nicht wirklich zu gebrauchen, es soll lediglich das Vorgehen nahelegen.
Wie bereits oben erwähnt soll die Präsentation, also das was der Benutzer zu sehen bekommt (üblicherweise das Formular, also die GUI) von der Logik getrennt werden. Deshalb dürfen in der View-Klasse nur Sachen stehen, die der Darstellung der Elemente dienen. Das was passiert wenn man eins dieser Elemente anklickt wird dann über den Controller gesteuert.
Die Berechnungen an sich stehen dann im Model, wo auch alle Objekte verweilen, die unser Programm nutzt.
Unser Demo Programm ist sehr einfach aufgebaut, wir haben nur vier Klassen:
Bild 2: Der Aufbau des Projekts
Bevor ihr euch wundert, das Programm soll uns später die Quadratwurzel einer Zahl berechnen.
An Bild 1 könnt ihr erkennen, dass die Controller Klasse die wichtigste ist, da sie eigentlich das Ganze Programm steuert und dafür sorgt, dass die View und das Model sich verständigen können. Deswegen muss die Controller Klasse die anderen Klassen kennen, die anderen brauchen sich gegenseitig aber nicht!
public class Main {
static WurzelController controller;
/**
* Diese Klasse wird nur dazu benutzt alle nötigen
* Komponenten zu Initialisieren und die erste
* View anzuzeigen
*/
public static void main(String [] args){
controller = new WurzelController();
controller.showView();
}
}
Die Klasse Main macht hier auch nichts anderes, als die anderen Klassen zu instanzieren und uns die View anzuzeigen.
An den Konstruktoren kann man auch die Abhängigkeiten erkennen. Eigentlich macht man der View auch das Model bekannt (siehe Bild 1), aber da unser Beispiel zu simpel ist können wir uns diese Bekanntschaft sparen.
Das Model ist ebenfalls sehr einfach aufgebaut, es enthält die nötigen Rechenoperationen die für unser Programm wichtig sind und bietet öffentliche Methoden mit denen der Controller die Werte abfragen kann
/**
* Das Model ist komplett unabhängig von den anderen
* Klassen und weiß nicht was um ihn herum geschieht.
* Es ist völlig egal ob man dieses Model aus einem
* Fenster oder einer Konsolen Eingabe verwendet -
* beiden würde funktionieren.
*/
public class WurzelModel {
long _value;
public WurzelModel(){
zurückSetzen();
}
public void zurückSetzen(){
this._value = 0;
}
public void berechneWurzel(long wert){
this._value = (wert * wert);
}
public long getWurzel(){
return this._value;
}
}
Wichtig hierbei ist, dass diese Klasse keine Beziehungen zu den anderen Klassen hat! Man muss sie so aufbauen, dass man sie ohne eine Änderung in einem anderen Projekt benutzen könnte.
Unsere View ist ganz typisch aufgebaut. Es werden die Steuerelemente initialisiert und auf der JForm plaziert, desweiteren muss die View Methoden bieten, mit denen man die ActionListener für die auf dem Formular liegenden Steuerelemente setzen kann. Über diese wird unser Controller mit der View kommunizieren. Dazu kommen noch die getter und setter Methoden für die Textfelder, diese werden benötigt, damit man aus dem Controller Zugriff darauf hat!
/* Die View-Klasse diese Enthält nur die Präsentation
* hier sollte man keinerlei Programmlogik finden
* alle Berechnungen und Reaktionen auf Benutzeraktionen
* sollten allesammt im Controller stehen
*/
public class WurzelView extends JFrame{
private JLabel lbl1 = new JLabel("Eingabe: ");
private JTextField txtEingabe = new JTextField(3);
private JButton cmdCalc = new JButton("Wurzen Berechnen >");
private JTextField txtErg = new JTextField(5);
private JButton cmdClear = new JButton("Zurüclsetzen");
public WurzelView(){
super("Wurzel Berechnen");
initForm();
}
/**
* Die JForm initialisieren und alle Steuerelemente
* darauf positionieren
*/
private void initForm(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.setBounds(200, 200, 500, 100);
this.add(lbl1);
this.add(txtEingabe);
this.add(cmdCalc);
this.add(txtErg);
this.add(cmdClear);
}
public void resetView(){
this.txtEingabe.setText("");
this.txtErg.setText("");
}
public String getEingabe(){
return this.txtEingabe.getText();
}
public void setErgebnis(String erg){
this.txtErg.setText(erg);
}
/**
* Funktionen bereitstellen, mit denen man später aus
* dem Controller die nötigen Listener hinzufügen kann
*/
public void setWurzelBerechnenListener(ActionListener l){
this.cmdCalc.addActionListener(l);
}
public void setResetFormListener(ActionListener l){
this.cmdClear.addActionListener(l);
}
}
Bleibt nur noch der Controller. Dieser ist auch sehr simpel aufgebaut:
/**
* Der Controller muss beide die View und das Model kennen
* da dieser für die Kommunikation zwischen den Beiden sorgt
*/
public class WurzelController {
private WurzelView _view;
private WurzelModel _model;
public WurzelController(){
this._model = new WurzelModel();
this._view = new WurzelView;
addListener();
}</pre>
<pre>
<div id="_mcePaste"> public void showView(){</div>
<div id="_mcePaste"> this._view.setVisible(true);</div>
<div id="_mcePaste"> }</div>
/**
* Die Listener, die wir aus den Internen Klassen generieren
* werden der View bekannt gemacht, sodass diese mit
* uns (dem Controller) kommunizieren kann
*/
private void addListener(){
this._view.setWurzelBerechnenListener(new WurzelBerechnenListener());
this._view.setResetFormListener(new ResetFormListener());
}
/**
* Inneren Listener Klassen implementieren das Interface ActionListener
*
* 1: Hier wird erst der eingegebene Wert aus der View geholt
* 2: Der Wert wird dem Model übergeben und die Wurzel berechnet
* 3: Die berechnete Wurzel wird aus dem Model geladen und
* 4: Wieder der View zum Darstellen übergeben
*
* ACHTUNG: Fehlerprüfung muss noch implementeirt werden
*/
class WurzelBerechnenListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
long wert = Long.valueOf(_view.getEingabe());
_model.berechneWurzel(wert);
_view.setErgebnis(String.valueOf(_model.getWurzel()));
}
}
/**
* Hier wird dem View und dem Model gesagt ihre gespeicherten
* Werte zu löschen.
*/
class ResetFormListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
_view.resetView();
_model.zurückSetzen();
}
}
}
Wie man sieht werden hier nur die dem Konstruktor übergebenen Referenzen auf die View und das Model gespeichert und dann die Erzeugten ActionListener der View übergeben.
Die ActionListener sind interne Klassen die nun automatisch von unserer View aufgerufen werden, wenn der Benutzer einen der Buttons klickt! Praktisch oder?
Wenn man die WurzelBerechnenListener Klasse anschaut kann man auch die Typische Kommunikation zwischen den Schichten sehen. Die View lößt ein Event aus, für dessen Abhandlung der Controller verantwortlich ist. Nun holt der Controller sich alle nötigen Daten aus der View (in diesem Fall ist es nur ein Wert, die Eingabe) und lässt das Model das Quadrat berechnen. Schließlich holt der Controller sich die berechneten Daten zurück und lässt die View diese anzeigen.
Im Grunde gar nicht kompliziert oder? So sieht das Fenster zur Laufzeit aus:
Bild 3: Das Programm zur Laufzeit
Wenn man ein neues Projekt anfängt sollte man sich natürlich erst einmal genau überlegen ob man die MVC Architektur benutzt, denn diese ist bei kleinen Projekten mit einem höheren Aufwand verbunden. Wenn man aber weiß, dass in absehbarer Zeit an dem Programm weitere Änderungen oder Erweiterungen vorgenommen werden sollte man MVC in Betracht ziehen!
ACHTUNG: Habe eben erst gemerkt, dass ich überall "Wurzel" geschrieben habe, das ergibt natürlich gar keinen Sinn!
oh mann, muss wohl sehr verwirrt gewesen sein! Quadrat müsste es natürlich heißen.
Keine Lust das nun alles nochmal zu ändern!
Die Sourcen könnt ihr hier laden: Download

Januar 29th, 2010 - 16:44
Bloggd: Tutorial: Model-View-Controller (MVC) Struktur in Java Projekten nutzen – http://blog.bigbasti.com/tutorial-model-... #java #mvc
via Twitoaster
Februar 8th, 2010 - 22:54
Also ich muss sagen, ich versuche schon seit längerem den MVC-Ansatz zu verstehen…jedoch habe ich nie ein Tutorial komplett gelesen, da es mich nie gefesselt hatte bzw. schon mittendrin so komplex war, dass die Motivation schnell fehlte…aber jetzt habe ich es mit diesem verstanden!
Vielen Dank!