MVC-Architektur

Camill

Bekanntes Mitglied
Hallo,

In den letzten Tagen habe ich mich ein wenig mit der MVC Architektur auseinandergesetzt, zur Übung wurde ein kleines Programm geschrieben (Calculator - kann zwei natürliche Zahlen Addieren, Subtrahieren, Multiplizieren oder Dividieren).
Wäre nett wenn jemand die Zeit und Lust dazu hat sich das einmal anzuschauen und mir mitzuteilen ob die MVC Architektur richtig umgesetzt wurde.

Model
Java:
package calculator.model;

import java.util.ArrayList;

public class CalculatorModel implements Calculator {

	private ArrayList<CalculatorObserver> observers = new ArrayList<CalculatorObserver>();
	private int result;

	@Override
	public void addition(int summand1, int summand2) {
		result = summand1 + summand2;
		for (CalculatorObserver observer : observers) {
			observer.newResult(new CalculatorEvent(result));
		}
	}

	@Override
	public void subtraction(int minuend, int subtrahend) {
		result = minuend - subtrahend;
		for (CalculatorObserver observer : observers) {
			observer.newResult(new CalculatorEvent(result));
		}
	}

	@Override
	public void multiplication(int multiplier, int multiplicand) {
		result = multiplier * multiplicand;
		for (CalculatorObserver observer : observers) {
			observer.newResult(new CalculatorEvent(result));
		}
	}

	@Override
	public void division(int dividend, int divisor) {
		result = dividend / divisor;
		for (CalculatorObserver observer : observers) {
			observer.newResult(new CalculatorEvent(result));
		}
	}

	@Override
	public void addCalculatorObserver(CalculatorObserver observer) {
		this.observers.add(observer);
	}
}
Java:
package calculator.model;

public interface Calculator {

    public void addition(int summand1, int summand2);
    public void subtraction(int minuend, int subtrahend);
    public void multiplication(int multiplier, int multiplicand);
    public void division(int dividend, int divisor);

    public void addCalculatorObserver(CalculatorObserver observer);
}
Java:
package calculator.model;

public interface CalculatorObserver {

    public void newResult(CalculatorEvent event);
}
Java:
package calculator.model;

public class CalculatorEvent {

	private int result;

	public CalculatorEvent(int result) {
		this.result = result;
	}

	public int getResult() {
		return result;
	}
}

View
Java:
package calculator.view;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import calculator.controller.CalculatorController;
import calculator.model.CalculatorEvent;
import calculator.model.CalculatorObserver;

public class CalculatorView implements ActionListener, CalculatorObserver {

	private CalculatorController controller;

	private JFrame frame;
	private JPanel panel;
	private JTextField textField;
	private JButton[] numberButtons;
	private JButton[] signButtons;

	public CalculatorView(CalculatorController controller) {

		this.controller = controller;
		this.init();
	}

	private void init() {

		frame = new JFrame("Calculator");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(100, 100, 0, 0);
		frame.setResizable(false);

		panel = new JPanel(new GridBagLayout());
		frame.add(panel);

		// arithmetic field
		textField = new JTextField();
		GridBagConstraints gbc_textField = new GridBagConstraints();
		gbc_textField.fill = GridBagConstraints.HORIZONTAL;
		gbc_textField.gridwidth = 5;
		panel.add(textField, gbc_textField);

		// buttons for numbers
		numberButtons = new JButton[10];
		for (int i = 0; i < numberButtons.length; i++) {
			numberButtons[i] = new JButton("" + i);
			numberButtons[i].addActionListener(this);
			GridBagConstraints gbc = new GridBagConstraints();
			if (i < 5) {
				gbc.gridx = i;
				gbc.gridy = 1;
			} else {
				gbc.gridx = i - 5;
				gbc.gridy = 2;
			}
			panel.add(numberButtons[i], gbc);
		}

		// buttons for signs
		signButtons = new JButton[5];
		signButtons[0] = new JButton("+");
		signButtons[1] = new JButton("-");
		signButtons[2] = new JButton("*");
		signButtons[3] = new JButton("/");
		signButtons[4] = new JButton("=");

		for (int i = 0; i < signButtons.length; i++) {
			signButtons[i].addActionListener(this);
			GridBagConstraints gbc = new GridBagConstraints();
			gbc.gridx = i;
			gbc.gridy = 3;
			gbc.fill = GridBagConstraints.HORIZONTAL;
			panel.add(signButtons[i], gbc);
		}

		frame.pack();
		frame.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {

		String text = ((JButton) arg0.getSource()).getText();
		if (text.equals("=")) {
			controller.calculateResult(textField.getText());
		} else {
			if (text.equals("+") || text.equals("-") || text.equals("*")
					|| text.equals("/")) {
				textField.setText(textField.getText() + " " + text + " ");
			} else {
				textField.setText(textField.getText() + text);
			}
		}
	}

	@Override
	public void newResult(CalculatorEvent event) {

		String message = "The result is " + event.getResult();
		String title = "Result!";
		JOptionPane.showMessageDialog(new JFrame(), message, title,
				JOptionPane.PLAIN_MESSAGE);
		textField.setText("");
	}
}

Controller
Java:
package calculator.controller;

import java.awt.EventQueue;

import calculator.model.CalculatorModel;
import calculator.view.CalculatorView;

public class CalculatorController {

	private CalculatorModel model;

	public static void main(String[] args) {

		EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				new CalculatorController();
			}
		});
	}

	private CalculatorController() {

		CalculatorView view = new CalculatorView(this);
		model = new CalculatorModel();
		model.addCalculatorObserver(view);
	}

	public void calculateResult(String string) {

		String[] strings = string.trim().split(" ");
		int nmb1 = Integer.parseInt(strings[0]);
		int nmb2 = Integer.parseInt(strings[2]);
		switch (strings[1].charAt(0)) {
		case '+':
			model.addition(nmb1, nmb2);
			break;
		case '-':
			model.subtraction(nmb1, nmb2);
			break;
		case '*':
			model.multiplication(nmb1, nmb2);
			break;
		case '/':
			model.division(nmb1, nmb2);
			break;
		default:
			break;
		}
	}
}

Gruß
 
Zuletzt bearbeitet:

GUI-Programmer

Top Contributor
Schaut auf den 1. Blick doch ganz ordentlich aus. Allerdings würde ich mir angesichts des Rechenbedarfs Calculator, CalculatorObserver, sowie CalculatorEvent sparen. Da reicht eine Klasse. Andererseits wäre sie so auch gut erweiterbar, aber dennoch.

Eine Kleinigkeit hast du meiner Meinung nach aber falsch verstanden: Controller ist nich (unbedingt) die ausführende Klasse, sondern in 1. Linie für Benutzereingaben, sprich in Java für die EventListener zuständig. Somit würde ich diese einfach unbenennen (z.B Main) und mir ne Controller - Klasse schreiben die den ActionListener (evtl. auch deinen CalculatorObserver) implementiert.

Mein MVC Muster siehe in MVC Ein JFrame, mehrere JPanels
 

Camill

Bekanntes Mitglied
Schaut auf den 1. Blick doch ganz ordentlich aus. Allerdings würde ich mir angesichts des Rechenbedarfs Calculator, CalculatorObserver, sowie CalculatorEvent sparen. Da reicht eine Klasse. Andererseits wäre sie so auch gut erweiterbar, aber dennoch.
Bei diesem kleinen Programm könnte man das natürlich ohne den ganzen Klassen lösen, werde demnächst aber an einem größeren Projekt Arbeiten deswegen das ganze auch schon mal hier "ausprobiert".

Eine Kleinigkeit hast du meiner Meinung nach aber falsch verstanden: Controller ist nich (unbedingt) die ausführende Klasse, sondern in 1. Linie für Benutzereingaben, sprich in Java für die EventListener zuständig. Somit würde ich diese einfach unbenennen (z.B Main) und mir ne Controller - Klasse schreiben die den ActionListener (evtl. auch deinen CalculatorObserver) implementiert.
Somit den ActionListener aus der View in den Controller(Gibt es eine andere sinnvolle Möglichkeit als Getter-Methoden für die Buttons anzulegen und im Controller dann den ActionListener "anzuhängen"?) und das eigentliche starten der Applikation aus dem Controller in eine eigene Klasse.

Werde ich mir mal anschauen.

Dankeschön für die Antwort - das Warten hat sich gelohnt ;)
 

Schandro

Top Contributor
Das Model wirkt halt sehr merkwürdig weil es im Prinzip nur Logik und keine Speicherung von Daten beinhaltet, aber bei einem kleinen Taschenrechner ist das Model schließlich so oder so unwichtig^^
 

GUI-Programmer

Top Contributor
@Camill: Wie bereits gesagt ist dein Programm halt erweiteterbar und somit (durchaus gut):
Vorerst: Unnötiger Arbeitsaufwand
Später: Zum Glück habe ich von Anfang an...
 

Camill

Bekanntes Mitglied
Habe mir nun das von dir erstellte Beispiel angeschaut und ein wenig gegoogelt, die Listener sollte ich wohl wircklich im Controller Implementieren.

Das Model wirkt halt sehr merkwürdig weil es im Prinzip nur Logik und keine Speicherung von Daten beinhaltet, aber bei einem kleinen Taschenrechner ist das Model schließlich so oder so unwichtig^^
Ja genau - bei größeren Projekten ändert sich dies natürlich ;)
 

Ähnliche Java Themen

Neue Themen


Oben