Presentation

Mixing Business with Presentation

User interfaces (presentation logic) can be volatile, while business logic is usually stable. Obviously the user interface depends on business logic, but if business logic also depends on presentation logic, then changes to the user interface can propagate into the business logic.

The Model-View-Controller Pattern

The Model-View-Controller Pattern consists of three roles:

Model: Class, package, or component encapsulating business logic
Views: The visible part of the user interface, controls + displays
Controllers: React to user input by updating the model

The pattern dictates that the model should be independent of the user interface (views + controllers).

Note that the same object can play the roles of view and controller.

In Java controllers are listeners.

Note that views must update their displays when the model changes state.

Example

In a spreadsheet application we might have:

Model: SpreadSheet
View: TableView displays the spreadsheet as a table
Controller: TableViewListener reacts to user input in the TableView by updating the corresponding cell in the spreadsheet.

Here's the design:

Note that there are no arrows pointing from the model to the other components. This implies that the model is independent of the user interface.

We can make this one way dependency clearer by placing the TableView and TableViewListener in a gui package and the SpreadSheet and Cell classes in a model package:

Swing Controls

The Swing architecture is loosely based on the Model-View-Controller Pattern.

See: http://java.sun.com/products/jfc/tsc/articles/architecture/

Roughly:

Model: ComponentModel
View: JComponent
Controller: ComponentListener

Here's the design:

The listener specifies the behavior or feel of the component. The view (JComponent) specifies the look of the component, and the model specifies the state of the component.

For simple controls like JButton, this is overkill, but it's quite useful for more complicated controls like JTable:

Model: Implementation of TableModel
View: JTable
Control: Implementor of TableModelListener

We can apply this to our spreadsheet. Here's the design:

Here's the code:

TablePanel.java

model.SpreadSheet.java

Event Delegation

Event Delegation is an implementation of the Publisher-Subscriber Pattern:

Publisher: Event Source
Subscriber: Event Listener

In Swing component models fire events that are passed to the component controller or listener:

Publisher: Component Model
Subscriber: Component Listener

Here's how this plays out in our spreadsheet example:

Publisher: Table Model
Subscriber: Table Model Listener
Concrete Publisher: SpreadSheet
Concrete Subscriber: TabelPanel

Here's how the spreadsheet implements setValueAt:

public void setValueAt(Object value, int row, int col) {
   cells[row][col].setValue(new Double((String)value));
   fireTableCellUpdated(row, col);
}

The TablePanel responds to this event by repainting itself:

public void tableChanged(TableModelEvent e) {
   repaint();
}

Multi-View Applications

In a multi-view application the user can open several views of the model.

In Excel, for example:

In Simple:

Note that there can be different types of views, too.

In a multi-view application we encounter the event notification problem. How will changes to the model made in one view be reflected in other open views.

Java programmers can implement views as internal frames that float inside of a desktop window.

An internal frame contains a TablePanel and is fairly straight forward:

TableFrame.java

A desktop contains table frames:

Viewer.java

Notice that all views are views of the same table model and therefore are automatically updated when the table is modified.

Listeners

Notice that every time the user selects Document/New, a new view is created. This is once again thanks to event delegation. In this case menu items fire action events that are passed to registered action listeners.