SLIDE 1 Software Engineering I (02161)
Model-View-Controller
- Assoc. Prof. Hubert Baumeister
DTU Compute Technical University of Denmark
Spring 2020
SLIDE 2 Layered Architecture
Important: ◮ No business logic in presentation layer or infrastructure/database layer ◮ No UI/GUI code in the application–/domain layer
Eric Evans, Domain Driven Design, Addison-Wesley, 2004
SLIDE 3
Example Vending Machine
Two different presentation layers; same application layer ◮ Swing GUI ◮ Command line interface Current Money: DKK 5 0) Exit 1) Input 1 DKK 2) Input 2 DKK 3) Input 5 DKK 4) Select banana 5) Select apple 6) Cancel Select a number (0-6): 5 Rest: DKK 2 Current Money: DKK 0 Dispensing: Apple
SLIDE 4 Model View Controller (MVC)
Invented by Trygve Reenskaug for Smalltalk-76/80
Presentation Layer Application/Domain Layer Model View paint update Controller processEvent
access view state access model state messages to model
◮ View: model state to display graphics ◮ Controller: mouse and keyboard events to messages to model ◮ Model: Business logic
SLIDE 5 MVC with Observer Pattern
handleEvent() doSomething() propertyChange(..) display() getState() propertyChange(..) display() getState() User c:Controller m:Model doSomething() v:View
SLIDE 6
MVC Example: Drawing Program
SLIDE 7 DrawingApp main Application Layer Presentation Layer «anonymous» MouseMotionAdapter mouseDragged(e: MouseEvent) «anonymous» MouseAdapter mousePressed(e: MouseEvent) PropertyChangeSupport «interface» PropertyChangeListener DrawingPanel propertyChange paint(g: Graphics) JPanel Point x: int y: int Drawing addPoint(p: Point) newLine draw(g: Graphics) Polyline getXValues: int[*] getYValues: int[*] getSize: int draw(g: Graphics) * model * *
SLIDE 8
MVC Example: Drawing Program
public class DrawingPanel extends JPanel implements PropertyChangeListener { Drawing model; public DrawingPanel(Drawing model) { this.model = model; model.addObserver(this); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { drawing.newLine(); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { drawing.addPoint(new Point(e.getX(),e.getY())); } }); } public void paint(Graphics g) { drawing.draw(g); } public void propertyChange(PropertyChangeEvent evt) { repaint(); } }
SLIDE 9
Drawing class
public class Drawing { private PropertyChangeSupport support = new PropertyChangeSupport(this); private List<Polyline> lines = new ArrayList<>(); public void newLine() { lines.add(new Polyline()); support.firePropertyChange("drawing", null, null); } public void addPoint(Point p) { lines.get(lines.size() - 1).add(p); support.firePropertyChange("drawing", null, null); } ... }
SLIDE 10 Java and Swing
Presentation Layer Application/Domain Layer «interface» PropertyChangeListener PropertyChangeSupport ApplicatonFacade Application main propertyChange(...) JPanel JFrame JTextField JLabel JButton «anonymous» ActionListener performAction(e: ActionEvent) «interface» EventHandler JComponent paint(g:Graphics) processEvent(e:Event) * model * *
SLIDE 11
Example Vending Machine
Two different presentation layers; same application layer ◮ Swing GUI ◮ Command line interface Current Money: DKK 5 0) Exit 1) Input 1 DKK 2) Input 2 DKK 3) Input 5 DKK 4) Select banana 5) Select apple 6) Cancel Select a number (0-6): 5 Rest: DKK 2 Current Money: DKK 0 Dispensing: Apple
SLIDE 12 Architecture
Application Layer VendingMachineTextUI Presentation Layer <<enumeration>> Fruit APPLE BANANA VendingMachineUI VendingMachine dispensedItem: Fruit {readOnly} currentMoney: int {readOnly} totalMoney: int {readOnly} restMoney: int {readOnly} input(money: int) select(f: fruit) cancel() Presentation Layer *
VendingMachine acts as the facade (Facade Design Pattern)
SLIDE 13
Presentation Layer: Swing GUI
public class VendingMachineUI extends implements PropertyChangeListener { private VendingMachine vendingMachine = new VendingMachine(10, 10); ... private JFrame topWindow = new JFrame(); private JButton fiveCrowns = new JButton(); private JTextField currentM = new JTextField(); ... private void initComponents() { fiveCrowns.setText("DKK 5"); fiveCrowns.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { fiveCrownsActionPerformed(evt); } } ) ... }; private void fiveCrownsActionPerformed(java.awt.event.ActionEvent evt) { vendingMachine.input(5); } ... public void propertyChange(PropertyChangeEvent evt) { currentM.setText("" + vendingMachine.getCurrentMoney()); ... } }
SLIDE 14 VendingMachineTextUI class
public void mainLoop(InputStream in, PrintStream out) throws IOException { ... do { showMenu(out); choice = Integer.valueOf(in.readLine()); ... } processChoice(number, out); } while (true); } private void showMenu(PrintStream out) { ...
3) Input 5 DKK"); ....
- ut.println("Select a number (0-6): ");
} private void processChoice(int number, PrintStream out) { switch (number) { ... case 3: vendingMachine.input(5); break; ... } }
SLIDE 15
VendingMachineTextUI class (cont.)
public void propertyChange(PropertyChangeEvent evt) { String type = evt.getPropertyName(); switch (type) { ... case NotificationType.CURRENT_MONEY: System.out.println("Current Money: DKK " + vendingMachine.getCurrentMoney()); break; ... } }
SLIDE 16
Advantages of using MVC and separation of layers
1 Presentation layer easily changed 2 Additional presentation layers can be added easily without having to reimplement the business logic 3 Automatic tests: test the application and domain layer: test ”under the GUI”