Gyakorlati alapok II.
A szoftverfejlesztés
Az MVC Java-nyelvben
Az alábbi fejezet Sallay András informatikatanár oktatási anyagára támaszkodik (www.szit.hu)
Az előző fejezetben az MVC-modell általános megközelítését tárgyaltuk meg. Ebben a fejezetben 3 példán keresztül ismerjük meg a modell Java-implementációját.
Az 1. példa egyetlen állományon belül oldja meg a modellt:
import
javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.FlowLayout;
class MainWindow extends JFrame {
private JButton calcButton = new JButton("Számít");
public JTextField baseField = new JTextField(10);
public JTextField heightField = new JTextField(10);
public JTextField resultField = new JTextField(10);
private JLabel baseLabel = new JLabel("alap:");
private JLabel heightLabel = new JLabel("magasság:");
MainWindow() {
resultField.setVisible(false);
add(baseLabel);
add(baseField);
add(heightLabel);
add(heightField);
add(resultField);
add(calcButton);
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
centerWindow(this);
setVisible(true);
}
public void addCalcButtonActionListener(ActionListener listener) {
calcButton.addActionListener(listener);
}
public static void centerWindow(java.awt.Window frame) {
java.awt.Dimension dimension = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = (int)((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int)((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
class Controller {
MainWindow mainWindow = new MainWindow();
Model model = new Model();
Controller() {
mainWindow.addCalcButtonActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
String baseStr = mainWindow.baseField.getText();
String heightStr = mainWindow.heightField.getText();
double base = Double.parseDouble(baseStr);
double height = Double.parseDouble(heightStr);
Double area = model.calcArea(base, height);
mainWindow.resultField.setText(area.toString());
mainWindow.resultField.setVisible(true);
mainWindow.pack();
}
});
}
}
class Model {
public double calcArea(double base, double height) {
if(base <= 0 || height <=0) {
throw new IllegalArgumentException();
}
return (base * height) /2;
}
}
class Main {
public static void main(String[]args) {
new Controller();
}
}
Végeredmény:
Nagyobb projektekben a modell-nézet-kontroller számára külön könyvtárat készítünk. A 2. példában a következő könyvtárszerkezetet alakítjuk ki:
Forrás - Source: www.szit.hu
MainFrame
package view;
import javax.swing.JFrame;
public class MainFrame extends JFrame {
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
}
Model.java
package model;
public class Model {
}
Controller.java
package controller;
import view.MainFrame;
import model.Model;
public class Controller {
MainFrame mainFrame = new MainFrame();
Model model = new Model();
public Controller() {
}
}
Haromszog.java
import controller.Controller;
class Haromszog {
public static void main(String[] args) {
new Controller();
}
}
Makefile
SOURCE=view/MainFrame.java \
model/Model.java \
controller/Controller.java \
Haromszog.java
all:
javac -cp . $(SOURCE)
run:
xterm -e "java -cp . Haromszog; read"
A 3. példában a háromszög területszámító program komplett megvalósítását látjuk, egységteszttel együtt. Tesztelni csak a model részt teszteljük, amelyben maga a számítás történik.
MainFrame
package view;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
public class MainFrame extends JFrame {
JPanel topPanel = new JPanel();
JLabel titleLabel = new JLabel("Háromszög területszámító");
JPanel bottomPanel = new JPanel();
JLabel baseLabel = new JLabel("alap:");
public JTextField baseField = new JTextField(5);
JLabel heightLabel = new JLabel("magasság:");
public JTextField heightField = new JTextField(5);
public JLabel resultLabel = new JLabel("eredmény:");
public JTextField resultField = new JTextField(5);
JButton calcButton = new JButton("Számít");
public MainFrame() {
topPanel.setLayout(new FlowLayout());
topPanel.add(titleLabel);
bottomPanel.setLayout(new BoxLayout(bottomPanel,
BoxLayout.X_AXIS));
bottomPanel.add(baseLabel);
bottomPanel.add(baseField);
bottomPanel.add(heightLabel);
bottomPanel.add(heightField);
bottomPanel.add(resultLabel);
bottomPanel.add(resultField);
bottomPanel.add(calcButton);
resultLabel.setVisible(false);
resultField.setVisible(false);
setLayout(new BoxLayout(getContentPane(),
BoxLayout.Y_AXIS));
add(topPanel);
add(bottomPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void addCalcButtonActionListener(ActionListener
listener) {
calcButton.addActionListener(listener);
}
}
ModelTest.java
package test;
import org.junit.Test;
import static org.junit.Assert.*;
import model.Model;
public class ModelTest {
Model model = new Model();
@Test
public void testCalcArea() {
assertEquals(525, model.calcArea(30,
35), 0);
assertEquals(900, model.calcArea(40,
45), 0);
}
@Test(expected = IllegalArgumentException.class)
public void tesztExceptionSzamitTerulet() {
model.calcArea(0, 35);
}
}
Model.java
package model;
public class Model {
public static double calcArea(double base, double height) {
if (base <= 0 || height <= 0) {
throw new IllegalArgumentException("Nem
megfelelő paraméterek");
}
return (base * height) / 2;
}
}
Controller.java
package controller;
import view.MainFrame;
import model.Model;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Controller {
MainFrame mainFrame = new MainFrame();
Model model = new Model();
public Controller() {
mainFrame.addCalcButtonActionListener(new
ActionListener(){
public void
actionPerformed(ActionEvent event) {
String
baseStr = mainFrame.baseField.getText();
double base =
Double.parseDouble(baseStr);
String
heightStr = mainFrame.heightField.getText();
double height
= Double.parseDouble(heightStr);
Double result
= model.calcArea(base, height);
mainFrame.resultField.setText(result.toString());
mainFrame.resultField.setVisible(true);
mainFrame.resultLabel.setVisible(true);
mainFrame.pack();
}
});
}
}
Haromszog.java
import controller.Controller;
class Haromszog {
public static void main(String[] args) {
new Controller();
}
}
Makefile
SOURCE=view/MainFrame.java \
model/Model.java \
controller/Controller.java \
Haromszog.java
all:
javac -cp . $(SOURCE)
run:
xterm -e "java -cp . Haromszog; read"
LINJUNIT=/usr/share/java/junit4.jar
testl:
javac -cp .:$(LINJUNIT) test/ModelTest.java
java -cp .:$(LINJUNIT) org.junit.runner.JUnitCore
test.ModelTest
WINJUNIT=c:\bin\SWScite\javalibs\junit-4.11.jar
WINHAMCREST=c:\bin\SWScite\javalibs\hamcrest-core-1.3.jar
testw:
javac -cp .;$(WINJUNIT);$(WINHAMCREST) test/ModelTest.java
java -cp .;$(WINJUNIT);$(HAMCREST) org.junit.runner.JUnitCore
test.ModelTest