Quick Start: Migrating to a Model 2 Architecture

Overview

This page presents the code changes necessary to migrate the example login application to a Model 2 architecture.

Updates to LoginScreen

LoginScreen needs two changes to make it follow a Model 2 architecture:

  • Allow ActionListeners to register themselves.
  • Fire an ActionEvent instead of directly setting the next screen.

Allow ActionListeners

Add the following code to LoginScreen:

private List actionListeners = new LinkedList();

...

public void addActionListener(ActionListener listener) {
   this.actionListeners.add(listener);
}

public void removeActionListener(ActionListener listener) {
   this.actionListeners.remove(listener);
}

Fire an ActionEvent

In the method attemptLogin(ActionEvent evt), change the lines:

Window win = (Window) getParent();
win.setContent(new PortalScreen());

to:

fireSuccessfulLoginEvent();

Then add the fireSuccessfulLoginEvent() method:

public void fireSuccessfulLoginEvent() {
   ActionEvent evt = null;
   Iterator it = this.actionListeners.iterator();
   ActionListener listener = null;
  
   evt = new ActionEvent(this, LoginScreen.CMD_SUCCESS);
  
   while (it.hasNext()) {
      listener = (ActionListener) it.next();
      listener.actionPerformed(evt);
   }
}

Finally, add a constant defining the action command used to signal a successful login:

public static final String CMD_SUCCESS = "successfulLogin";

Review of LoginScreen Migration

Our LoginScreen class now follows a Model 2 architecture. Notice that the class no longer has any direct knowledge of the application in which it resides. This indicates a healthy partitioning of responsibilities between the different types of objects. The screen is now de-coupled from the application in which it is used.

Updates to Application (the EchoInstance)

It is usually convenient to separate the logic that receives events and makes navigation decisions from the code that loads the next screen. Thus, we will write a separate method that sets the main window's contents for each screen to be loaded in our application. This allows more intricate screen setups to be performed away from the confusion of the navigation logic and be reused when a screen can be accessed from different locations.

The application needs three changes for migration to a Model 2 architecture:

  • Define the screen loader methods.
  • Implement ActionListener.
  • Register for ActionEvents on the LoginScreen.

Define the Screen Loader Methods

Put the logic that loads each screen in our application into its own method:

public void gotoLoginScreen() {
   LoginScreen screen = new LoginScreen();
   this.window.setContent(screen);
}

public void gotoPortalScreen() {
   PortalScreen screen = new PortalScreen();
   this.window.setContent(screen);
}

Implement ActionListener

Update the Application class declaration to include: implements ActionListener. Then implement the actionPerformed(ActionEvent) method as follows:

public void actionPerformed(ActionEvent evt) {
   String cmd = evt.getActionCommand();
  
   if (LoginScreen.CMD_SUCCESS.equals(cmd)) {
      gotoPortalScreen();
   }
}

Handling Large Applications
For large applications, it is useful to move the callback methods and decision logic to its own class, which may be an inner class of your EchoInstance or a stand-alone class.

Register for ActionEvents

Now that the EchoInstance can handle callbacks from the LoginScreen, we will hook it up to listen for them when the LoginScreen is loaded. Update the gotoLoginScreen() method defined above to include the line: screen.addActionListener(this);.

Conclusion

You have seen how to develop an application that separates its nevigation logic from its screen processing logic. You have learned how to migrate a Model 1 Echo application to a flexible, maintainable Model 2 architecture.

It may seem that the amount of effort is disproportional to the proposed benefits. For small applications such as our example, this is probably true. However, for even modestly-sized applications and applications that experience significant requirements evolution, such as on projects using agile methodologies, the avoidance of more brittle designs overshadows the extra effort required use a Model 2 paradigm.



< Screen Navigation