MVC, Klappe, die 3625ste... :)

kaoZ

Top Contributor
Aloha und noch einmal des Verständnis halber, wäre es klasse wenn ihr mir sagen könntet ob ich dieses Pattern nun endlich richtig verstanden habe :D, hierzu halte ich mein Beispiel so einfach wie möglich !

Bespiel

Konkretes Problem :

-Farbwechsel eines in einem Frame enthaltenen Panels über einen Button, ggf. späteres hinzufügen von weiterer Funktionalität bzw. Austausch der Komponenten

Lösungsansatz nach MVC Pattern ohne Observer! :

Model :

Java:
public class Model {

	JComponent component;
	Color color;
	
	public Model() {}
	
	public void changeColor(JComponent component, Color color){
		component.setBackground(color);
	}
}

Das Model liefert ausschließlich die Daten , bzw. die Funktionalität, das Model kennt weder die View , noch den Controller ( außer bei implementiertem Observer Pattern), und ist somit komplett austauschbar.

View :

Java:
public class View {

	private JFrame frame;
	private JPanel panel;
	private JButton btn;
	
	public View() {
		frame = new JFrame("MVC Test");
		frame.setSize(300,150);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		panel = new JPanel(new BorderLayout());
		btn = new JButton("Farbe wechseln");
		
		panel.add(BorderLayout.PAGE_END, btn);
		
		frame.add(BorderLayout.CENTER, panel);
	}
	
	public void addListener(ActionListener listener){
		btn.addActionListener(listener);
	}
	
	public void setVisible(){
		frame.setVisible(true);
	}
	
	public JPanel getPanel()			{return this.panel;}
}

Die View dient nur als Schnittstelle zur Sicht auf die Daten, stellt Methoden bereit um listener hinzuzufügen und bietet getter an welche eine Referenz auf benötigte Komponenten liefert.
Die View kennt weder Controller noch das Model, und ist wie auch das Model austauschbar


Der Controller :

Java:
public class Controller implements ActionListener{
	
	View view;
	Model model;
	
	public Controller(Model model) {
		this.view = new View();
		this.model = model;
		
		view.addListener(this);
		view.setVisible();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		model.changeColor(view.getPanel(), Color.BLUE);
	}
}

Der Controller Initialisiert die View, und hält Referenzen auf das Model und die View, er dient zur Kommunikation und Steuerung zwischen den einzelnen Elementen, er bereitet die Daten auf und führt dementsprechend Aktionen aus dem Model aus welche in der View abgerufen/angefordert werden, der Kontroller hält Referenzen auf Model und View, ist aber trozdem mit etwas mehraufwand auch austauschbar.

TestMvc :

Java:
public class TestMvc {
	
	public static void main(String[] args) {
		new Controller(new Model());
	}
}

Instanziert nur einen neuen Controller mit entsprechendem Model

Nun 3 Fragen :

1. Sind meine Annahmen korrekt ?

2. Wenn ich jetzt anstelle von Listenern , z.B in einer JMenuBar oder JToolbar, Actions verwende, welche sich zur Steuerrung der Verarbeitung kümmern, dann sind diese doch die Controller , oder täusche ich mich ?

3. Wenn ich nun dazu übergehe das Observer-Pattern zu implementieren, dann muss ich es ermöglichen das sich interessenten ja bei den zu beobachtenden Komponenten an und abmelden können, z.B das sich die View , als beobachter beim Controller registrieren kann , oder der Controller beim Model,
Wie würde ich , bzw. wie würdet ihr dies auf das oben genannte Beispiel umsetzen , und wie sehe die implementierund dazu aus ?

Vielen Dank vorab :)


Wäre super wenn sich dann nochmal jemand anschauen könnte und mir möglichst fachliche rückmeldung geben würde.
 

turtle

Top Contributor
Im Prinzip richtig, aber...

In Swing findet sich keine Reinform des MVC-Models, sondern eine Verquickung von View und Controller. Durch diese Vereinfachung lassen sich die Benutzeroberflächen leichter programmieren, wobei wir nur wenig Flexibilität einbüßen. Das neue Model wird statt MVC auch Model View Presenter (MVP-Pattern) genannt.

Aus der Insel
 

kaoZ

Top Contributor
Danke !

Das hab ich schon gelesen, mir ging es nur darum die Architektur dahinter erst einmal richtig nachvollziehen zu könne, mir ist auch bewusst das im "normalFall" das Observer-Pattern implementiert wird welches dann über dessen update methoden dann z.B ein neuzeichnen der View veranlasst sobald sich das Model ändert.

Mir ging es darum nachvollziehen zu können , wie das ganze jetzt mit Actions aussehen würde, wenn die Annahme allerdings korrekt ist , und diese dann als Controller zwischen der View und dem Model welches die Funktionalität liefert fungieren, wäre meine Frage auch schon beantwortet :)

Ist denn die Annahme richtig , das ich dazu der jeweiligen Action eine Referenz auf das Aktuelle Model übergeben muss ? ( oder eine eine Referenz auf den HauptController welches eine Referenz auf das Model hält) sonst könnte ich ja aus den Actions heraus garnicht auf die Datenschicht zugreifen ?!:rtfm:

[EDIT]
mit Verquickung von View und Controller meinst du das die View eine Referenz darauf hält ?
[/EDIT]
 
Zuletzt bearbeitet:

Harry Kane

Top Contributor
Mir ging es darum nachvollziehen zu können , wie das ganze jetzt mit Actions aussehen würde, wenn die Annahme allerdings korrekt ist , und diese dann als Controller zwischen der View und dem Model welches die Funktionalität liefert fungieren, wäre meine Frage auch schon beantwortet :)
Ich würde sagen, daß jedes Objekt, welches Aktionen auslöst, die zur Änderung eines Models führen, als Controller fungieren. Deshalb: ja, Actions, wenn sie diese Bedingung erfüllen sind Controller (IMHO). Actions sind im MVC Kontext gar nix "besonderes". Sie machen einem unabhängig von architektonischen Finessen nur aufgrund der Kapselung das Leben etwas leichter.

Ist denn die Annahme richtig , das ich dazu der jeweiligen Action eine Referenz auf das Aktuelle Model übergeben muss ? ( oder eine eine Referenz auf den HauptController welches eine Referenz auf das Model hält) sonst könnte ich ja aus den Actions heraus garnicht auf die Datenschicht zugreifen
Nochmal ja. Der Controller muss das Model kennen, an dem er selber Änderungen vornimmt oder dem er sagt, es solle sich selbst aktualisieren. Oder er muss jemanden kennen der jemanden kennt, der... aber dann wirds natürlich kompliziert.
Ein Controller kann natürlich Referenzen auf mehrere Models halten und allen das Kommando zum ändern geben.

[EDIT]
mit Verquickung von View und Controller meinst du das die View eine Referenz darauf hält ?
[/EDIT]
So wie ich das verstanden habe, ist damit gemeint, daß ein und dasselbe Objekt als View und Controller fungieren kann. Z. B. eine JList: sie dient als View für ein ListModel, wertet aber auch Selektionen, d. h Benutzereingaben, aus und aktualisiert damit ihr ListSelectionModel.

An deinem Beispiel gefallen mir übrigens ein paar Dinge nicht:
a) Das Model ändert aktiv die View. Normalerweise ist es umgekehrt: die View holt sich die Informationen aus dem Model. Das Model ändert nur seinen eigenen Inhalt. Dann wird durch einen geeigneten Mechanismus dafür gesorgt, daß die View von der Änderung erfährt und sich alle benötigten Informationen zur Darstellung neu beschafft.
b) In der View passiert mir zu viel. Eine View sollte nur eine Komponente einer GUI sein und nicht, wie in deinem Fall, für den Aufbau quasi der gesamten Applikation verantwortlich sein.
c) Deine View ist gar keine View, sondern das JPanel der View ist die View.
Ich habs hier mal etwas umgestellt. Hier wird auch gezeigt, wie das ganze mit dem Observer-Pattern funktioniert:
Java:
public class MVCDemo2 {
    public static void main(String[] args){
        JFrame frame = new JFrame("MVC Demo 2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        View view = new View();
        View2 view2 = new View2();
        Model model = new Model();
        frame.getContentPane().add(view, BorderLayout.WEST);
        frame.getContentPane().add(view2, BorderLayout.EAST);
        JButton button = new JButton("Farbe links und rechts wechseln");
        JButton button2 = new JButton("Farbe nur rechts wechseln");
        button.addActionListener(new Controller(model, view));
        button2.addActionListener(new Controller2(model, view2));
        frame.add(button, BorderLayout.NORTH);
        frame.add(button2, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }
}
//Das Model beinhaltet nur die Daten. 
class Model{
    private Color[] colors = new Color[]{Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.CYAN};
    private Color color = Color.red;
    private ArrayList<ModelChangeListener> listeners  = new ArrayList<ModelChangeListener>();;
    int index = 0;
    void changeColor(){
        index = (index < colors.length - 1) ? ++index : 0;
        this.color = colors[index];
        for(ModelChangeListener mcl: listeners){
            mcl.modelChanged();
        }
    }
    Color getColor(){
        return this.color;
    }
    void addChangeListener(ModelChangeListener l){
        listeners.add(l);
    }
}
//Die View zeigt die Daten an. Die View braucht eine Referenz auf das Model,
//um die Daten zu beschaffen
class View extends JComponent{
    private Model model;
    View(){
        setPreferredSize(new Dimension(200, 200));
    }
    void setModel(Model model){
        this.model = model;
    }
    protected Model getModel(){
        return this.model;
    }
    protected void paintComponent(Graphics g){
        if(model == null) return;
        super.paintComponent(g);
        g.setColor(model.getColor());
        g.fillRect(0, 0, 200, 200);
    }
}
interface ModelChangeListener{
    void modelChanged();
}
//Um über Änderungen am Model informiert zuw erden, kann sich die View auch beim
//Model als Observer registrieren.
class View2 extends View implements ModelChangeListener{
    View2(){
        super();
    }
    public void setModel(Model model){
        super.setModel(model);
        model.addChangeListener(this);
    }
    public void modelChanged(){
        repaint();
    }
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.fillOval(95, 95, 10, 10);
    }
}
//Der Controller bringt Model und View zusammen. Er wertet Benutzeraktionen aus
//und leitet ggf. Änderungen am Model ein.
class Controller implements ActionListener{
    private Model model;
    private View view;
    Controller(Model model, View view){
        this.model = model;
        this.view = view;
        view.setModel(model);
    }
    public void actionPerformed(ActionEvent ae){
        model.changeColor();
        view.repaint();
    }
}
class Controller2 implements ActionListener{
    private Model model;
    Controller2(Model model, View2 view){
        this.model = model;
        view.setModel(model);
    }
    public void actionPerformed(ActionEvent ae){
        model.changeColor();
    }
}
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
das würde also in meinem konkreten fall bedeuten , auf mein Beispiel bezogen

ich biete in meiner view einen setter an , welcher die farbe des Panels ändert, im model biete ich nur eine Methode an welche mir die Daten dazu liefert, sprich die farbe, und im Controller erfolgt der aufruf dann umgekehrt

z.b so in der actionPerformed Methode

Java:
view.setPanelColor(model.getColor());

anstatt eine Referenz auf den panel an das model zu liefern

Da ich von unterwegs aus schreibe verzeiht mir bitte das ich mich möglichst kurz halte was den source Code angeht
 
Zuletzt bearbeitet:

Harry Kane

Top Contributor
das würde also in meinem konkreten fall bedeuten , auf mein Beispiel bezogen

ich biete in meiner view einen setter an , welcher die farbe des Panels ändert, im model biete ich nur eine Methode an welche mir die Daten dazu liefert, sprich die farbe, und im Controller erfolgt der aufruf dann umgekehrt

z.b so in der actionPerformed Methode

Java:
view.setPanelColor(model.getColor());
Nö. Die View holt sich die Daten selbst aus dem Model. Die Daten werden weder von dem Model noch von dem Controller in die View gepusht. Dazu müsste Model oder Controller nämlich wissen, an welchen Daten aus dem Model die View interessiert ist. Bei einem einfachen Model, was nur eine Farbe liefert, stellt sich die Frage nicht, bei komplexeren Models abe schon.
 

kaoZ

Top Contributor
Nö. Die View holt sich die Daten selbst aus dem Model. Die Daten werden weder von dem Model noch von dem Controller in die View gepusht

Ok, dies kann so doch aber nur funktionieren wenn die View beim Model als Beobachter registriert ist , und insofern sich die Daten im Model ändern , das Model alle Beobachter über diese Änderung an den Daten informiert.

Und das kann nur funktionieren wenn man das Observer Pattern implementiert , oder sehe ich das nun Falsch ?

Bedeutet also

Aktionen im View werden über den Controller über Daten im Model verarbeitet, ändern sich diese Daten informiert das Model alle Beobachter darüber, in meinem Beispiel würde das bedeuten , die View erhält die information das sich die Daten ( in diesem Fall die Farbe geändert hat ) holt sich die Farbe aus dem Model und stößt ein Zeichnen mit der neuen Farbe des Panels an .

Ist das Soweit Korrekt ?
 

Joose

Top Contributor
Ok, dies kann so doch aber nur funktionieren wenn die View beim Model als Beobachter registriert ist , und insofern sich die Daten im Model ändern , das Model alle Beobachter über diese Änderung an den Daten informiert.

Und das kann nur funktionieren wenn man das Observer Pattern implementiert , oder sehe ich das nun Falsch ?

Bedeutet also

Aktionen im View werden über den Controller über Daten im Model verarbeitet, ändern sich diese Daten informiert das Model alle Beobachter darüber, in meinem Beispiel würde das bedeuten , die View erhält die information das sich die Daten ( in diesem Fall die Farbe geändert hat ) holt sich die Farbe aus dem Model und stößt ein Zeichnen mit der neuen Farbe des Panels an .

Ist das Soweit Korrekt ?

Soweit korrekt, aber bei der Formulierung "die View ... holt sich die [DATEN] aus dem Model" aufpassen, die View sollte das Model nicht kennen (daher kann sie auch nicht wissen wie sie die Daten bekommt). Die Daten werden vom Model ebenfalls mitgeteilt (PropertyChanged).
 

kaoZ

Top Contributor
Ok, nochmal langsam , die View ist also als Beobachter beim Model registriert, und erhält insofern sich im model die Daten ändern die Meldung das sich die Daten geändert haben ?

Soweit korrekt ?

Sollte dies der Fall sein stößt die View an , die erforderlichen Komponenten neu zu Zeichnen , in meinem Beispiel den JPanel ( View ) mit der sich geänderten Farbe.
 

kaoZ

Top Contributor
Ok, nochmal langsam , die View ist also als Beobachter beim Model registriert, und erhält insofern sich im model die Daten ändern die Meldung das sich die Daten geändert haben ?

Soweit korrekt ?

Sollte dies der Fall sein stößt die View an , die erforderlichen Komponenten neu zu Zeichnen , in meinem Beispiel den JPanel ( View ) mit der sich geänderten Farbe.

Wobei Harry Kane in seinem code folgendes als Kommentar eingefügt hat

//Die View zeigt die Daten an. Die View braucht eine Referenz auf das Model,
//um die Daten zu beschaffen

ebend das soll doch denke ich nicht sein ? Die View kennt das model denke ich doch nur über das implementieren des Observer Interfaces da die View beim Model als Beobachter registriert ist . ?
 

Joose

Top Contributor
ebend das soll doch denke ich nicht sein ? Die View kennt das model denke ich doch nur über das implementieren des Observer Interfaces da die View beim Model als Beobachter registriert ist . ?

Genau die View kennt das Model nicht!!!
Die View kennt es nicht einmal mit dem Observer Pattern. Bei diesem ist die View als Observer (nicht als View) wo registriert. Sie bekommt irgendwann vl die Information, dass sich Property X geändert hat auf Wert Y
 

kaoZ

Top Contributor
Genau die View kennt das Model nicht!!! Sie bekommt irgendwann vl die Information, dass sich Property X geändert hat auf Wert Y

So dachte ich mir das nämliche auch, sonst entsteht ja wieder abhänigkeit und das Model / die View sind nicht ohne weiteres austauschbar.

Wenn sich nun Property X ändert , erhält die View das diese als Observer im Model "angemeldet" ist, eine Benachrichtigung und kann sich daraufhin selbst neu Zeichnen , bzw. die Teile der GUI die sich anhand der Daten ändern müsste (in meinem Beispiel das JPanel welches als Blick auf die Daten fungiert, hoffe das war nun eine korrekte Beschreibung, falls ja hab ich das Pattern glaube ich endlich gecheckt, nun muss ich nurnoch die Umsetzung mit Observer Pattern auf die Reihe bekommen , ohne ( mit ensprechenden Gettern und Settern ) sitzt alles schon soweit, Daten, Logik und View voneinander zu trennen,

Allerdings muss ich sagen das ich an verschiedenen Stellen immer unterschiedliche Beschreibungen lese,

einmal ist das Model für Daten und Logik zuständig, an anderer Stelle ist dann wiederum der Controller für die Logik zuständig und das Model hält nur die Daten bereit.

Ist das gewollt ? ggf. Auslegungssache ?
 

Joose

Top Contributor
Genau so ist es! :)
Das MVC Pattern im einfachen zu verstehen ist nicht schwer. Je komplexer das Programm und die GUI wird um so schwieriger wird das saubere umsetzen von MVC. Hat man den Dreh aber mal raus ist es generell einfach.

Patterns wurden von einigen Personen definiert, Wie es andere dann verstehen und wiedergeben ist natürlich unterschiedlich und da kann es zu Differenzen kommen.
Generell wurden die viele Design Pattern von der GoF nieder geschrieben, und darauf verweisen viele. GangOfFour

Ich persönliche finde, dass das Model rein zum Datenhalten benutzt werden sollte (bzw. minimale Logik bei Listen etc). Die Logik sollte man im Controller oder Services "verstecken".
Aber DesignPatterns sind generell nur eine Anleitung, je nach deinem Problem kannst du es anpassen/erweitern.
 

Harry Kane

Top Contributor
Bei diesem ist die View als Observer (nicht als View) wo registriert. Sie bekommt irgendwann vl die Information, dass sich Property X geändert hat auf Wert Y
Ich hoffe du meinst "die View bekommt sicher und unverzüglich die Information, dass sich die Property geändert hat".
Ich persönlich halte es nur für eine und nicht für DIE Möglichkeit, die View mit PropertyChangeEvents über Änderungen des Models zu infomieren. Bei einfachen Views, die nur eine bestimmte Eigenschaft eines Models anzeigen sollen, mag das ganz praktisch sein, bei komplexeren Models dürfte das schnell ziemlich unübersichtlich werden.
Beispiel: die Visualierung einer Punktmenge in einem Chart. Wenn sich ein Punkt in dem data model ändert, muss sich die View aktualisieren und alle Punkte neu zeichnen. Dazu braucht sie aber Zugriff auf alle Punkte!
Anderes Beispiel: eine View dient als Anzeige für eine List. Werden neue Elemente der List hinzugefügt oder existierende gelöscht, braucht die View für ihre Aktualisierung ebenfalls Zugriff auf alle Elemente.
In solchen Fällen könnte die View natürlich Informationen cachen, aber es ist ja nicht Aufgabe der View Daten zu halten.
Was mir übrigens an dem Standard PropertyChangeEvent nicht gefällt, ist, daß es nicht typisiert ist und praktisch nur Objects kennt.
So dachte ich mir das nämliche auch, sonst entsteht ja wieder abhänigkeit und das Model / die View sind nicht ohne weiteres austauschbar.
Was meinst du mit "ohne weiteres"? Wenn eine View eine Referenz auf ein Model bekommt und sich bei Bedarf die benötigten Daten zur Anzeige aus dem Model holt, muss das natürlich über eine definierte Schnittstelle geschehen, die vom Model zu implementieren ist. Dann kann allerdings jedes Objekt, das diese Schnittstelle implementiert, als Model wirken. Die View muss natürlich nicht das ganze Model kennen, sondern nur den Teil, die durch die Schnittstelle beschrieben wird.
Ich persönlich finde es sehr bequem, wenn ich z. B. einer JList oder JTable (oder einer selbst geschriebenen View) direkt ein neues Model verpassen kann anstatt einen separaten Controller schreiben zu müssen, der das Model kennt und der dafür sorgt, dass sich Views, die sich bei ihm anmelden, als PropertyChangeListener auf dem Model registriert werden.
Patterns wurden von einigen Personen definiert, Wie es andere dann verstehen und wiedergeben ist natürlich unterschiedlich und da kann es zu Differenzen kommen.
[...]Aber DesignPatterns sind generell nur eine Anleitung, je nach deinem Problem kannst du es anpassen/erweitern.
Da kann ich mal ausnahmsweise ;) zustimmen. Wie man ein bestimmtes Muster auf ein bestimmtes Problem anwendet, ist nicht nur abhängig vom Programmierer, sondern auch vom Problem. Manchmnal mag es vorteilhaft sein, wenn Model und View nur sehr lose gekoppelt sind, manchmal nachteilig.
@Kaoz: Bin übrigens schon sehr gespannt, wann die ganzen quasi-philosophischen Diskussionen beendet sind und du uns richtigen Code präsentierst:).
 

kaoZ

Top Contributor
@Kaoz: Bin übrigens schon sehr gespannt, wann die ganzen quasi-philosophischen Diskussionen beendet sind und du uns richtigen Code präsentierst.


Ich auch :lol:

Ne Spaß bei Seite, ich arbeite mich noch ins Observer-Pattern ein , da ich nebenbei auch noch nen Berufsleben habe (und eben kein Informatiker/Programmierer bin) dauert das immer etwas, da ich es Quasi "nebenbei" mache ;)

[EDIT]Haha :D , ich seh grade , ich Programmiere übrigens seit genau einem Jahr, da hab ich mich nämlich hier angemeldet ^^[/EDIT]
 
Zuletzt bearbeitet:

Harry Kane

Top Contributor
Ne Spaß bei Seite, ich arbeite mich noch ins Observer-Pattern ein , da ich nebenbei auch noch nen Berufsleben habe (und eben kein Informatiker/Programmierer bin) dauert das immer etwas, da ich es Quasi "nebenbei" mache ;)
Mir gehts ähnlich: nebenberuflich Programmierer, hauptberuflich User.:)
Mas mir gestern abend noch später eingefallen ist: Der Ansatz, den ich hier beschrieben habe, ist ein Beispiel für Views, die jeweils nur eine Eigenschaft eine Models beobachten.
An dem ganzen könnte man architektonisch einiges aussetzen:
  • Die View ist nicht austauschbar. View (oder Editor) und Controller sind unauflöslich miteinander verbunden.
  • Es gibt überhaupt keine Verbindung zwischen dem Model (bzw. dem Item) und der View. Wenn sich das Model ändert, bekommt die View davon nix mit. Dies ist auch nicht notwendig, weil die einzige Änderung am Model, die für die View interessant ist, von der View (bzw. dem Editor) selbst ausgelöst wird.
Komischerweise funktioniert das ganze trotzdem prächtig, zumindest im Hinblick auf die Kriterien "Erweiterbarkeit" und "Wiederverwendbarkeit".
Dann noch ein frohes Schaffen.
 

kaoZ

Top Contributor
So ähnlich war ja auch mein erster Ansatz, ohne Observer Pattern , allerdings stoße ich von außen (Controller) die Aktionen in der View an.

Dafür kennt die View weder das Model, noch das Model die View oder den Controller, demnach wäre alles austauschbar, Model , sowie view und auch Controller.

Allerdings musste ich so für alle Aktionen die in der View passieren sollen , öffentliche bzw. auch private "setter" anbieten um darauf vom Controller aus zugreifen zu können.

Ich werd mir das einfach nochmal in ruhe anschauen , und dann versuchen mal das Beispiel mit dem ändern der Hintergrund Farbe des Panel nach MVC in Verbindung mit Observer pattern umzusetzen, so das der View ( Sicht auf das Model / nicht die Gui, die Klasse war in meinem Beispiel etwas unglücklich benannt ) selbst dafür sorgt sich bei Änderungen im Model neu zu zeichnen.
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Ok, ich glaube ich habs :

Model (beobachtbares Objekt):

Java:
public class Model extends Observable {

	Color color;
	
	public Model() {}
	
	public void setColor(Color color){
		this.color = color;
		setChanged(); // <<-- Daten haben sich geändert !
		notifyObservers(this); // <<-- benachrichtige alle Beobachter !
	}
	
	public Color getColor(){
		return this.color;
	}
}

Controller ( Steuerung ):

Java:
public class Controller implements ActionListener{
	
	Gui gui;
	Model model;
	
	public Controller(Model model) {
		this.gui = new Gui();
		this.model = model; 
		this.gui.addListener(this);
		
		model.addObserver(this.gui); // <<-- dem Model Beobachter zuweisen ( hier die Gui )
		gui.setVisible();
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		model.setColor(Color.GREEN);
	}
}

und die Gui mit View(JPanel als sicht auf das Model) als Beobachter :

Java:
public class Gui implements Observer{

	private JFrame frame;
	private JPanel view;
	private JButton btn;
	
	public Gui() {
		frame = new JFrame("MVC Test");
		frame.setSize(300,150);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		view = new JPanel(new BorderLayout());
		btn = new JButton("Farbe wechseln");
		
		view.add(BorderLayout.PAGE_END, btn);
		
		frame.add(BorderLayout.CENTER, view);
	}
	
	public void addListener(ActionListener listener){
		btn.addActionListener(listener);
	}
	
	public void setVisible(){
		frame.setVisible(true);
	}

	@Override
	public void update(Observable observable, Object obj) {
		if(obj instanceof Model){
			this.view.setBackground(((Model) obj).getColor());
		}
	}
}

Funktioniert auf jeden Fall, hier wäre es ja so das Das Model die Änderungen Preisgibt sobald welche Stattfinden und alle Beobachter benachrichtigt,

sonst könnte man ja noch im Beobachter mit
Code:
hasChanged();
abfragen (z.B alle paar sekunden ) ob sich Daten im Model geändert haben und falls dem so sein sollte daraufhin die view aktualisieren , oder ?!

[EDIT]
Was ich so nur irgendwie unschön finde ist der DownCast von Obj zu Model in der View, anders wird es aber nicht funktionieren da ich ja kein zugriff auf die Methoden des Models bekomme da diese ja in Object nicht existieren, gibt es da noch andere Weg , außer die Explizite Typprüfung über instanceof und den Cast auf die Speziallisierung oder wird das so standardmäßig so gemacht um zwischen denn Auslösern des "Events" zu unterscheiden ?
[/EDIT]

Und vorallem :

1. Ist die Gui immer das Beobachtende Objekt ?

2. macht es Sinn wie in dem UML Diagrammen auch den Controller zu Beobachten ? und wenn ja , wann ?

3. Ist die annahme korrekt das "view" in jedem Fall für die jeweilige Sicht auf die Daten im Model steht ? Sprich bei einer ArrayList wäre dann die view ( also die Sicht ) auf diese Daten z.B eine JTable , oder auch eine einfache JTextArea, oder auch beides, je nachdem wie die Daten vom Controller gesteuert werden.

Und noch 2 annahmen :

4. Alles was Aktionen ausführt und dafür sorgt das sich Daten ändern , ist in der Regel ein Controller, egal ob über ein implementiertes Interface oder die Ableitung von AbstractAction etc...

5. Modelle sind im Grunde nur Value Objects (VO) welche Daten Kapseln und geringe Funktionale Logik bieten um z.B ihre Daten von außen zu ändern / auf diese zugreifen zu können .
 
Zuletzt bearbeitet:

Joose

Top Contributor
Ich hoffe du meinst "die View bekommt sicher und unverzüglich die Information, dass sich die Property geändert hat".

Mit dem "irgendwann" meinte ich eben irgendwann, sollten sich am Model Daten ändern, wird die View informiert (dann natürlich unverzüglich) ;)

Bei einfachen Views, die nur eine bestimmte Eigenschaft eines Models anzeigen sollen, mag das ganz praktisch sein, bei komplexeren Models dürfte das schnell ziemlich unübersichtlich werden.

Jein, das gibt es natürlich Mittel und Wege (Pattern erweitern etc).

Beispiel: die Visualierung einer Punktmenge in einem Chart. Wenn sich ein Punkt in dem data model ändert, muss sich die View aktualisieren und alle Punkte neu zeichnen. Dazu braucht sie aber Zugriff auf alle Punkte!
Anderes Beispiel: eine View dient als Anzeige für eine List. Werden neue Elemente der List hinzugefügt oder existierende gelöscht, braucht die View für ihre Aktualisierung ebenfalls Zugriff auf alle Elemente.
In solchen Fällen könnte die View natürlich Informationen cachen, aber es ist ja nicht Aufgabe der View Daten zu halten.

Ja dann gib der View einfach alle Punkte, bzw. die vollständige neue Liste und nicht nur die geänderten Sachen.

Was meinst du mit "ohne weiteres"?

Bei einer sauberen Implementierung von MVC sollte man folgende Codezeilen nach belieben austauschen können

Java:
View v = new SimpleViewOfWeather();
...
View v = new ExtendedViewOfWeather();

Sprich es reicht eine Zeile anzupassen um andere Daten angezeigt zu bekommen.
 

kaoZ

Top Contributor
Letztendlich sollte der View egal sein Welche Daten Sie darstellt, genauso im Umkehrschluß sollte dem Model egal sein welche View seine Daten nach außen hin sichtbar macht :)

Wichtig ist soweit ich es diesem Pattern nun entnehmen kann , das die einzelnen "Bauteile" austauschbar sind und ich z.B auch Daten aus einem Model mit mehreren Views in mehreren Formen Darstellen kann, wie es z.B bei Diagrammen etc. der Fall ist, und ggf. zu späterem Zeitpunkt weitere views hinzukommen können die diese Daten Darstellen, ebenso können weitere Modelle hinzukommen welche von den gleichen Views dargestellt werden können ( erweiterbarkeit ) :)
 
Zuletzt bearbeitet:

Neue Themen


Oben