swing mvc application layering a layer is a collection of components that perform similar tasks....

19
Swing MVC Swing MVC

Upload: byron-wright

Post on 04-Jan-2016

222 views

Category:

Documents


0 download

TRANSCRIPT

Swing MVCSwing MVC

Application LayeringApplication LayeringA Layer is a collection of components that A Layer is a collection of components that Perform similar tasks. Perform similar tasks. Isolate implementation details from the code that uses the layer. Isolate implementation details from the code that uses the layer. Does not make assumptions about the code using the layer. Does not make assumptions about the code using the layer. These properties imply that in a layered architecture, a layer can These properties imply that in a layered architecture, a layer can

make use of the layers underneath it but not of the layers lying make use of the layers underneath it but not of the layers lying above it. above it.

A layer communicates with the layer beneath it through interfaces.A layer communicates with the layer beneath it through interfaces.

The Façade PatternThe Façade Pattern

A Façade is used to provide a simple A Façade is used to provide a simple interface to a complex subsystem.interface to a complex subsystem.

In the context of UI, a façade helps In the context of UI, a façade helps identify and isolate server calls.identify and isolate server calls.

public interface BakeryFacade {public interface BakeryFacade {

Customer insertCustomer(Customer customer) throws BakeryException;Customer insertCustomer(Customer customer) throws BakeryException;

Customer findCustomer(String phone) throws BakeryException;Customer findCustomer(String phone) throws BakeryException;

Customer updateCustomer(Customer customer) throws BakeryException;Customer updateCustomer(Customer customer) throws BakeryException;

Order placeOrder(Order order) throws BakeryException;Order placeOrder(Order order) throws BakeryException;

List getOrders() throws BakeryException;List getOrders() throws BakeryException;

List getCustomerOrders(Customer customer);List getCustomerOrders(Customer customer);

}}

Façade OptionsFaçade Options

One façade for the whole applicationOne façade for the whole application Keeps implementation simpleKeeps implementation simple May start becoming crowdedMay start becoming crowded

One façade per type of operationOne façade per type of operation One façade per ‘service’ type keeps One façade per ‘service’ type keeps

code organizedcode organized More work if more than one More work if more than one

implementations are desired.implementations are desired.

The MVC componentsThe MVC components Model – A Model – A representation representation of the application data of the application data

suitable for displaying the UIsuitable for displaying the UI View – The collection of visual components thatView – The collection of visual components that

comprise the UIcomprise the UI Controller – Provides UI with behaviorController – Provides UI with behavior

Executes business logic through the façade.Executes business logic through the façade. Performs UI-level business logic and validationPerforms UI-level business logic and validation Instructs the model to populate the viewInstructs the model to populate the view

Web MVCWeb MVC

The view knows only how to display a The view knows only how to display a prescribed model. There is no logic prescribed model. There is no logic attached.attached.

The model is a simple transformation of The model is a simple transformation of the application data logic (e.g. as a Map)the application data logic (e.g. as a Map)

The controller receives requests from The controller receives requests from the view, processes them by applying the view, processes them by applying business logic and validation, changes business logic and validation, changes the model, and populates the view.the model, and populates the view.

Example of Web MVCExample of Web MVC public ModelAndView handleRequest(HttpServletRequest request, public ModelAndView handleRequest(HttpServletRequest request,

HttpServletResponse response) throws ServletException, HttpServletResponse response) throws ServletException, IOException {IOException {

Map context = new HashMap();Map context = new HashMap();String command = getCommand(request);String command = getCommand(request);User user = getUser(request);User user = getUser(request);if ("ViewStandings".equals(command)) {if ("ViewStandings".equals(command)) {

context.put("league",facade);context.put("league",facade);} else if ("ViewGames".equals(command)) {} else if ("ViewGames".equals(command)) {

context.put("user",user);context.put("user",user); context.put("admin", facade); context.put("admin", facade);

. . .. . .} else if ("EditGame".equals(command)) {} else if ("EditGame".equals(command)) {

long id = Long.parseLong(request.getParameter("id"));long id = Long.parseLong(request.getParameter("id"));Game game = (Game) facade.getGame(id);Game game = (Game) facade.getGame(id);context.put("game",game);context.put("game",game);

} else if("EditGameDate".equals(command)) {} else if("EditGameDate".equals(command)) {long id = Long.parseLong(request.getParameter("id"));long id = Long.parseLong(request.getParameter("id"));

Game game = (Game) facade.getGame(id);Game game = (Game) facade.getGame(id);context.put("game",game);context.put("game",game);

} else if ("ShowGames".equals(command)) {} else if ("ShowGames".equals(command)) {String name = request.getParameter("id");String name = request.getParameter("id");Team team = facade.getTeam(name);Team team = facade.getTeam(name);context.put("team",team);context.put("team",team);

} else if("SubmitGameDate".equals(command)) } else if("SubmitGameDate".equals(command)) … …

} else {} else {context.put("message","Page not found for context.put("message","Page not found for "+request.getRequestURI());"+request.getRequestURI());return new ModelAndView("Error",context);return new ModelAndView("Error",context);

}}return new ModelAndView(command,context);return new ModelAndView(command,context);

}}

<html><html><head><title>ViewGames</title></head><head><title>ViewGames</title></head><body><body>

<h2>Locates</h2><h2>Locates</h2>

<table border=1" cellspacing="2" cellpadding"=1"><table border=1" cellspacing="2" cellpadding"=1"> <th>Date</th><th>Home</th><th>Visitor</th><th>Score</th><th>Date</th><th>Home</th><th>Visitor</th><th>Score</th>

#foreach ($game in $admin.Games)#foreach ($game in $admin.Games)<tr><tr><td><td>#if ( $user.canChangeDate($game) )#if ( $user.canChangeDate($game) ) <<a href="EditGameDate.htm?a href="EditGameDate.htm?id=$game.Id">$game.Date</a>id=$game.Id">$game.Date</a>#else#else $game.Date$game.Date#end#end</td></td><td>$game.HomeTeam.Name</td><td>$game.HomeTeam.Name</td><td>$game.VisitingTeam.Name</td><td>$game.VisitingTeam.Name</td><td><td>#if ( $user.canChangeScore( $game) )#if ( $user.canChangeScore( $game) ) <a href="EditGame.htm?id=$game.Id">$game.Score</a><a href="EditGame.htm?id=$game.Id">$game.Score</a>#else#else $game.Score$game.Score#end#end</td></td></tr></tr>

#end#end</table></table>

<p/><p/><a href="index.html">Home</a><a href="index.html">Home</a>

</body></body></html></html>

The ‘right’ level for MVCThe ‘right’ level for MVC

UIs are built hierarchically. You combine UIs are built hierarchically. You combine components to create a panel. Then combine components to create a panel. Then combine panels to create a screen. It is important to panels to create a screen. It is important to decide at which level MVC applies. decide at which level MVC applies.

The component level is not the correct The component level is not the correct granularity for MVC granularity for MVC where behaviors are where behaviors are tightly linked to the view. (Swing Model-UI tightly linked to the view. (Swing Model-UI delegate)delegate)

MVC works well at the panel and screen MVC works well at the panel and screen level.level.

GUI Design PrinciplesGUI Design Principles Use a facade to access business logic - Hides business Use a facade to access business logic - Hides business

logic implementation details and make the UI logic implementation details and make the UI independent of the number of physical tiers.independent of the number of physical tiers.

Design user interfaces at the component and not the Design user interfaces at the component and not the container level. For example, extend JPanel and not container level. For example, extend JPanel and not JFrame - Enables reuse of views. For example, the JFrame - Enables reuse of views. For example, the application may use single-frame, popup frames, application may use single-frame, popup frames, internal frames, docable frames, et cetera.internal frames, docable frames, et cetera.

Access the view through an interface - Makes it easier Access the view through an interface - Makes it easier to switch view implementations. Allows controllers to to switch view implementations. Allows controllers to be unit-tested with mock views.be unit-tested with mock views.

Use an assembler class to “wire” the components Use an assembler class to “wire” the components together – Easy to change dependencies.together – Easy to change dependencies.

Introduce dependencies in the constructor – Avoid Introduce dependencies in the constructor – Avoid ending up with unsatisfied dependencies.ending up with unsatisfied dependencies.

MVC For SwingMVC For Swing The view accesses the model through an interface (example, TableModel)The view accesses the model through an interface (example, TableModel) The model sends updates to the view by registering it as a listener The model sends updates to the view by registering it as a listener

(example, TableModelListener)(example, TableModelListener) The controller manipulates the view through an interface.The controller manipulates the view through an interface. The controller manipulates the model either directly or through The controller manipulates the model either directly or through

interfaces.interfaces. The controller accesses business logic through a façade.The controller accesses business logic through a façade.

AdvantagesAdvantages

Server-side business logic can be updated Server-side business logic can be updated independently of the UI (Façade).independently of the UI (Façade).

Client-side business logic can be updated Client-side business logic can be updated without affecting the view (Controller).without affecting the view (Controller).

The view can be replaced without The view can be replaced without affecting the controller.affecting the controller.

The controller can be tested without The controller can be tested without instantiating GUI components.instantiating GUI components.

Testing the controllerTesting the controllerpublic class CustomerViewController {public class CustomerViewController {

. . .. . .

public void addCustomer() {public void addCustomer() {Customer customer = customerView.getCustomer();Customer customer = customerView.getCustomer();if (ValidationUtil.isEmpty(customer.getLastName())) {if (ValidationUtil.isEmpty(customer.getLastName())) {

bakeryView.reportMessage("Last name must bakeryView.reportMessage("Last name must be set.");be set.");

return;return;}}if (ValidationUtil.isEmpty(customer.getFirstName())) {if (ValidationUtil.isEmpty(customer.getFirstName())) {

bakeryView.reportMessage("First name must bakeryView.reportMessage("First name must be set.");be set.");

return;return;}}if (ValidationUtil.isEmpty(customer.getPhone())) {if (ValidationUtil.isEmpty(customer.getPhone())) {

bakeryView.reportMessage("Phone must be bakeryView.reportMessage("Phone must be set.");set.");

return;return;}}try {try {

customer = customer = facade.insertCustomer(customer);facade.insertCustomer(customer);

customerView.setCustomer(customer);customerView.setCustomer(customer);

bakeryView.reportMessage("Customer added.");bakeryView.reportMessage("Customer added.");} catch (BakeryException ex) {} catch (BakeryException ex) {

bakeryView.reportMessage("Insertion failed.");bakeryView.reportMessage("Insertion failed.");customerView.clear();customerView.clear();

}}}}

public class CustomerViewControllerTest extends public class CustomerViewControllerTest extends TestCase {TestCase {

private CustomerViewController controller;private CustomerViewController controller; private MockBakeryFacade facade = new private MockBakeryFacade facade = new

MockBakeryFacade();MockBakeryFacade(); public void setUp() {public void setUp() { controller = new controller = new

CustomerViewController(facade,customerView,bakCustomerViewController(facade,customerView,bakeryView);eryView);

}} public void testAddCustomer() {public void testAddCustomer() { Customer customer = new Customer();Customer customer = new Customer(); customerView.setCustomer(customer);customerView.setCustomer(customer); controller.addCustomer();controller.addCustomer(); assertEquals("Last name must be assertEquals("Last name must be

set.",bakeryView.getMessage());set.",bakeryView.getMessage()); customer.setLastName("last");customer.setLastName("last"); controller.addCustomer();controller.addCustomer(); assertEquals("First name must be assertEquals("First name must be

set.",bakeryView.getMessage());set.",bakeryView.getMessage()); customer.setFirstName("first");customer.setFirstName("first"); controller.addCustomer();controller.addCustomer(); assertEquals("Phone must be assertEquals("Phone must be

set.",bakeryView.getMessage());set.",bakeryView.getMessage()); customer.setPhone("123");customer.setPhone("123"); controller.addCustomer();controller.addCustomer(); assertEquals("Customer assertEquals("Customer

added.",bakeryView.getMessage())added.",bakeryView.getMessage())}}

Replacing the UIReplacing the UI

The Role of ActionsThe Role of Actions

Actions transmit information about Actions transmit information about user activities.user activities.

Each action can function as a controller Each action can function as a controller for the screen that originated.for the screen that originated.

Or delegate to the controller of the Or delegate to the controller of the screen.screen.

The second way is preferable since:The second way is preferable since: An action may originate from different An action may originate from different

components.components. Several actions may share common code.Several actions may share common code.

MVC versus MVAMVC versus MVA

Model - View - Actions Model – View - Controller

RecipeRecipe Write the models.Write the models. Create a view by arranging visual Create a view by arranging visual

components in a Panel. Do not attach any components in a Panel. Do not attach any listeners to the components (example, listeners to the components (example, CustomerPanel).CustomerPanel).

Make the view implement an interface Make the view implement an interface (example CustomerView).(example CustomerView).

Write a controller with constructor Write a controller with constructor dependencies on the façade and view dependencies on the façade and view interfaces. Manipulate the view via interfaces. Manipulate the view via interface methods or through the model.interface methods or through the model.

Link the view actions to the controller.Link the view actions to the controller.

ModificationsModifications

Connect actions to components by Connect actions to components by using a registry.using a registry.

Create the model in the controller.Create the model in the controller. Create the controller in the view.Create the controller in the view. For complex screens, write an MVC For complex screens, write an MVC

for each sub-view and create a for each sub-view and create a master controller that manipulates master controller that manipulates the individual components.the individual components.

Sample ApplicationSample Application

Thank you!Thank you!