Java 2 Platform, Micro Edition (J2ME) Mobile Information Device Profile (MIDP) is undoubtedly the dominant mobile phone programming platform today. The number of J2ME-enabled phones and J2ME applications continues to rapidly grow. However, working with J2ME is often complex. This isn't because J2ME is a sophisticated platform, but because J2ME is a constrained platform. Although MIDP is popular for building interactive applications, such as games, on mobile devices, it frequently exposes its weakness and limitations. Creating simple interactive content with MIDP is often complicated and requires repetitive programming tasks. This consequently burdens many developers.

After working on several MIDP projects, I found that many recurring problems could be solved with well-defined design patterns. I chose several design patterns that fit my problem scenarios and then tailored those patterns to comply with J2ME platform constraints (especially application size and performance constraints).

In this article, I examine four design patterns and strategies to implement interactive content on mobile devices. Each pattern has its unique role in creating a maintainable and reusable framework. You can download the source code for these patterns from Resources.

To understand this article's material, you should be familiar with MIDP's building blocks such as MIDlets, Display, and high-level user interface components in the javax.microedition.lcdui package. Readers also need basic Unified Modeling Language (UML) knowledge to read the design diagrams. If you are unfamiliar with these technologies, now is a good time to get up to speed. Resources are provided below.

Cascading Menu pattern

Let's start with the most interesting pattern: Cascading Menu. A menu is a fundamental way to navigate an application on constrained devices. A cascading menu has a long history on older electronic devices such as digital organizers and legacy terminals. System functionalities are organized in a hierarchy of nested menu options. Figure 1 is an example of a cascading menu for a city guide application. When users select a menu option, it takes them to a submenu with another list of available options. Users continue to navigate down the menu system until they hit the menu hierarchy's end node, which usually instructs the system to perform a function (e.g., retrieve relevant data).

Figure 1. A city guide application using Cascading Menu

This user interface format is commonly found in Wireless Application Protocol (WAP)-based content. By defining each menu option as an anchor (or link), Wireless Markup Language (WML) makes Cascading Menu a very simple system to implement. However, this is not the case in the MIDP world.

If you use MIDP's high-level (yet very constrained) user interface components, you might choose to implement several List objects. Each List object implements a menu screen with an options list. Upon a selection event, a CommandListener, the controller, determines which menu option was selected and updates the screen with another List object that represents the submenu. This solution is viable when you have only two or three choices in your menu system. If you add more menu screens to the hierarchy (say, 10 menus), it becomes a complicated approach. You would need to create 10 different List subclasses (Menu1Class, Menu2Class, Menu3Class) for the corresponding menu screens. These menus are difficult to manage and maintain. The dispatching logic between menus becomes a complex network of menu options and screens.

Fortunately, we can create a reusable and maintainable menu system. Another popular pattern, the Model-View-Controller (MVC) pattern, can shed some light on this situation. The MVC pattern offers maintainable and reusable user interfaces by separating the responsibilities of the model, view, and controller. The model is a data structure that represents the content behind the user interface application. The view is a visual component that displays content and receives user input. The controller serves as a bridge between model and view by implementing the logic and workflow to update the model and view.

The Cascading Menu pattern is a scaled-down version of the MVC pattern. We identify the menu hierarchy as this formula's model. We must implement a view component that can adapt to an arbitrary complex data model and reflect the model's current state. In other words, we build and maintain the menu model independently from the view component. The view component renders the menu screens based on the current menu model. The view component updates the screens when the menu model updates. Any changes to the menu hierarchy will automatically modify the presentation. Rearranging the menu system is just a matter of updating the menu tree data model.

Figure 2. Cascading Menu UML diagram

Figure 2 is the Cascading Menu pattern's UML diagram. The MenuElement class is our data model implementation. We use MenuElement to create a menu tree structure. Each MenuElement instance represents a node in this tree, and there are two node types: parent nodes (or menu containers) and child nodes (or menu items). For example, Main Menu (in Figure 1) is a parent node (or menu container). Shops, Restaurants, and Attractions are the Main Menu's child nodes (or menu items). We establish this relationship using the addChild() method.

Listing 1 shows how Figure 1's menu hierarchy is built. Once the data model is created, we feed it into our view component, MenuList. MenuList is a subclass of MIDP List and is responsible for displaying menu items as a list. MenuList can be reused in many menu-based applications because its behavior is driven by the menu data model. The showMenu() method instructs MenuList to display the Main Menu. MenuElement handles navigation logic. When a menu item is selected, the current MenuElement determines the item's associated object during addChild(). If the associated object is another menu screen (i.e., another MenuElement object), it replaces the current menu with the later one using MenuList.showMenu().

A user will eventually reach a menu item that triggers some action. We can create this link by adding a MenuElement associated with a MDisplayable object. The interface method onDisplay() is called when a user selects that menu item. We can perform the necessary action with onDisplay(). Listing 2 shows an onDisplay() implementation.

Listing 1. Build a menu hierarchy with MenuElement

   // Create three menus.
   // Use MenuElement for a menu container and
   // use MenuElement also for menu item in the container.
   // Link each menu item to a sample Mdisplayable.
   MenuElement menu3 = new MenuElement( "Attractions" );
   menu3.addChild( new MenuElement( "Museum"), new SampleMenuAction() );
   menu3.addChild( new MenuElement( "Art Galleries"), new SampleMenuAction() );
   menu3.addChild( new MenuElement( "Exhibitions"), new SampleMenuAction() );
   
   MenuElement menu2 = new MenuElement( "Restaurants" );
   menu2.addChild( new MenuElement( "Bakeries"), new SampleMenuAction() );
   menu2.addChild( new MenuElement( "Coffee Shop"), new SampleMenuAction() );
   menu2.addChild( new MenuElement( "Diner"), new SampleMenuAction() );
   
   MenuElement menu1 = new MenuElement( "Shops" );
   menu1.addChild( new MenuElement( "Automotives"), new SampleMenuAction() );
   menu1.addChild( new MenuElement( "Books"), new SampleMenuAction() );
   menu1.addChild( new MenuElement( "Fashions"), new SampleMenuAction() );
   
   // Create the Main Menu,
   // and link the menu item to the menu containers created above.
   MenuElement main = new MenuElement( "Main Menu" );
   main.addChild( new MenuElement( "Shops"), menu1 );
   main.addChild( new MenuElement( "Restaurants"), menu2 );
   main.addChild( new MenuElement( "Attractions"), menu3 );
   
   // Show the Main Menu, this will make the Main Menu as the current screen
   menulist.showMenu( main );

Listing 2. onDisplay() implementation

public class SampleMenuAction extends TextBox implements MDisplayable
{
   
   public void onDisplay( MenuElement e )
   {
      this.setString( "You have selected menu item "+e.text );
      
      // Sample implementation that takes different action
      // based on different menu item being selected   
      if ( e.text.equals("Museum") )
      {
         //
         // Code to retrieve Museum directory
         // and display it in this text box
         //
      } else if ( e.text.equals("Art Galleries") )
      {
         //
         // Code to retrieve Art Galleries directory
         // and display it in this text box         
         //
      } else if ( e.text.equals("Exhibitions") )
      {
         //
         // Code to retrieve Exhibitions directory
         // and display it in this text box         
         //
      }
      
   }
}

Different MenuElements are associated with different MDisplayable implementations so that specific actions perform accordingly. MenuList is responsible for the visual rendering of all menu screens. Using MenuElement and various MDisplayable implementations, we can build a scalable menu system while keeping the structure clean and easily maintainable.

Wizard Dialog pattern

Many desktop applications use wizards in installation tools or configuration tools. In a wizard application, users are prompted through a series of screens. Each screen asks one or two questions. Two actions are allowed in wizard applications: Next and Back actions. Users press the Next button to proceed to the next screen. Users press the Back button to return to the previous screen and alter a previous answer. On mobile devices, wizard-style interaction involves a wireless application asking a series of questions to gather user input before performing an action. This is essentially a replacement for a Web input form, which doesn't fit well on mobile devices.

Let's look at an example—a local restaurant's search tool. This search tool uses city names and keywords as search criteria. The wizard application is implemented in two different Form classes. One Form contains a ChoiceGroup with a list of predefined city names. Another Form contains a TextField for users to input keywords. Each Form must have a Back command and Next command for navigation between pages. To make this example more interesting, users must enter as least three characters in the keyword input field.

Figure 3. A sample wizard application

A wizard application consists of several dialogs, all of which are linked sequentially by Back and Next commands. An important requirement is to allow developers to decouple these Forms from each other and control the screen flow separately. Developers should focus only on building the dialogs' content, not on the repeated components that control the flow. Another pattern, the Mediator pattern, provides a clean and elegant way to achieve this. A mediator is a middleman component that controls several related components. Figure 4 shows the Wizard Dialog pattern's UML diagram. The mediator is the WizardEngine class, and each individual dialog is a WDialog subclass. By subclassing the WDialog class, developers can focus their efforts on building the wizard's content. WizardEngine handles the screen flow automatically.

Figure 4. Wizard Dialog UML diagram

The WDialog class is an abstract subclass for the MIDP Form class. It allows your application to manipulate the WDialog as an ordinary Form object. When subclassing the WDialog class, you must implement an abstract method, initDialog(). The method's implementation builds the Form's screen content for gathering user input. The following is an initDialog() example that builds a form to prompt for city names selection.

Listing 3. initDialog() implementation that prompts for city names

public class WPage2 extends WDialog
{
   ChoiceGroup question1;
   
   public void initDialog()
   {
      setTitle("Step 2");
      
      question1 = new ChoiceGroup("Select a city name to search", ChoiceGroup.EXCLUSIVE, new String[]{"Toronto", "Ottawa", "Waterloo"}, null );
      
      append( question1 );
   }
}

Oftentimes, an application needs to validate user input before proceeding to the wizard's next screen. In our example, we require users to enter at least three characters for the keyword field. WDialog provides optional onEnter() and onLeave() methods for implementing data validation. The onLeave() method invokes every time a user moves to the next screen. An onLeave() implementation checks the data inputted by a user on the current screen. If the data is not valid according to its business rules, onLeave() returns WDialog.REJECT; otherwise it returns WDialog.OK. The framework will ensure the user cannot flip to the next screen if WDialog.REJECT is returned.

Similarly, the onEnter() method invokes when a WDialog screen is about to appear on the device. If this screen is ready to be shown, WDialog.OK is returned; otherwise, WDialog.REJECT is returned, and the framework will take the user back to the previous screen. The mechanism provides opportunities for a WDialog implementation to validate the prerequisites and post-requisites of entering and leaving a screen. The following is an example of onLeave() that checks the keyword field. An alert screen displays if the user enters less than three characters.

Page 2 of 2

Listing 4. onLeave() implementation that checks for keywords

   public int onLeave( int dir )
   {
      if ( dir == WDialog.FORWARD )
      {
         // Question2 is a text box
         String answer = question2.getString();
         // Make sure user has entered 3 characters, and set the answer to a global variable
         if ( answer.length() < 3 )
         {
            // Show an alert screen
            Alert alert = new Alert("Bad Inpt");
            alert.setString( "You must enter at least 3 characters for keyword" );
            super.engine.getDisplay().setCurrent( alert, this );
            return WDialog.REJECT;
         } else
         {
            Wizardlet.answer2 = answer;
            return WDialog.OK;
         }
      } else
         return OK;
   }

The Wizard Dialog pattern allows developers to focus on their applications' user experience and screen flow, rather than on the wizard application's screen-by-screen wiring. Not only does Wizard Dialog save development time, it also reduces coding errors.

Pagination pattern

Mobile devices obviously have very limited screen real estate; they usually hold less than 10 lines of text. In many mobile applications, pagination is a hideous process. During pagination, large content pages break into multiple smaller pages; each contains a subset of the complete content. Users view the complete content by paging through the subset using a More or Next command.

In our restaurant search example, a wide search may result in 200 matches. This can divide into 10 pages, each page containing 20 matches in the list. Applications with pagination are more user friendly than those without because it takes less keystrokes to reach the target item. In some devices, pagination is also necessary for performance reasons. I have seen developers put 1,000 items in a single MIDP List, and the target phone consequently cannot respond to a single request. It takes a lot of memory and processing power to show 1,000 strings on a mobile phone.

The Pagination pattern provides a component that automates the paging process. This pattern also creates a clear separation between the data model and the view component. The data model in this case is the complete dataset (e.g., the 200 search matches). The data model does not need to know how the data breaks up to fit the display. The view component creates multiple content pages from the complete dataset. This is similar to a graphical user interface (GUI) toolkit (view) automatically providing a scroll bar to scroll a large image (the data) on a desktop application.

Figure 5. Pagination UML diagram

The Pagination pattern is a viewer-specific pattern that can be fully implemented in one class, PagableList. PagableList is a MIDP List subclass. Your application can treat this as an ordinary List class and perform usual List operations on it. You can add items and commands, and register command listeners. But it is not an ordinary List on the inside.

PagableList is a proxy to the original List because it overrides some of the methods. Internally, it holds the entire dataset and manages a sublist of it. It maintains a cursor that points to the currently displayed sublist index. It registers two built-in commands: the More and Previous commands. When users hit the More command, PagableList automatically advances to the next set of sublists and displays them on the screen. Similarly, when users hit the Previous command, PagableList rolls the cursor back to the previous dataset and puts them on the screen. By managing an internal cursor, users can quickly page through each data subset.

PagableList is a ready-to-use component. No additional work is required to enable pagination for your application. You simply create an instance of PagableList instead of a List and add data to it using the append() method. Since PagableList is a List subclass, it supports all List behavior, and you can cast its type into List throughout your application. This code fragment shows how to use PagableList:

Listing 5. PagableList sample usage

   PagableList pagablelist = new PagableList( "Paging", List.IMPLICIT);
   
   // 'this' refer to the current MIDlet
   Display.getDisplay(this).setCurrent(pagablelist);
   
   for ( int i=0; i< 100; i++ )
   {
      pagablelist.append( "Item  #"+i, null );
   }

PagableList implements a proxy pattern. By encapsulating the original List from the outside, PagableList puts additional functionality on top of List. The original proxy pattern suggests encapsulation by using a placeholder to control access to the subject. I modify it to include encapsulation by subclassing and overriding the List's interface. This approach allows me to preserve List's interface and type hierarchy, making it easier to use and lowering this pattern's overhead. Small optimizations like this can greatly improve design pattern usage in constrained J2ME environments.

Slide Show pattern

A slide show is another common form of interactive content usually viewed on desktops. A slide show is a sequence of screens that displays in a specific order. Each slide contains texts, images, or a mixture of both. For this article's purpose, we only consider the autopilot-mode slide show. The sequence appears as it is programmed; users cannot control the sequence's pace or order. A pause occurs between each slide so users have enough time to view and read a slide's content. The application controls the slide show's start and stop. The slide show also stops when it reaches the end of the sequence. The slide show requires the ability to add and remove slides easily without impacting other slides already implemented. The dependency between slides must be minimal.

Figure 6. Example slide show sequence

Similar to the Wizard Dialog solution previously discussed, a mediator flexibly decouples related screens. A slide show application shares some similarities with a wizard application in that they both involve multiple screen displays. In this solution, we encapsulate all the slide show's behavior into one class: SlideEngine. The SlideEngine class is an execution engine of the slide show sequence. Each slide is an implementation of the MIDP Displayable class. For text slides, we use TextBox. For image slides, we use Form with ImageItems or a custom Canvas implementation. Since every slide must be set into the Display object to display on a device screen, SlideEngine also holds a reference to the current MIDlet Display object during initialization. A sequence is a series of alternating Displayable objects. A time interval representing each slide's display duration follows each Displayble object (slide). The longer the interval, the longer a slide stays before the next slide displays. Let's put all these requirements into a UML diagram.

Figure 7. Slide Show UML diagram

The sequence creation is simple: Add Displayable objects into SlideEngine. Create MIDP user interface (UI) components, such as Form and TextBox, in the usual way. Then add these objects to the sequence in SlideEngine using the addSlide() method. The addSlide() method takes two parameters: a Displayable object that represents the slide and an integer that represents the slide's duration (in milliseconds).

Listing 6. Slide show implementation

    // Create a slide show engine with Display object as parameter.
    // 'this' pointer refers to current MIDlet.
    engine = new SlideEngine( Display.getDisplay(this ) );
    // Create 3 slides. All the slides are formed here.
    // You can use something else.
    Form f1 = new Form( "Slide 1");
    f1.append( "This is slide number 1" );
    Form f2 = new Form( "Slide 2");
    f2.append( "This is slide number 2" );
    Form f3 = new Form( "Slide 3");
    f3.append( "This is slide number 3" );
    // Add the slides to engine, each slide stays on screen
    // for 2 seconds.
    engine.addSlide( f1, 2000 );
    engine.addSlide( f2, 2000 );
    engine.addSlide( f3, 2000 );
    // Start the slide show
    engine.startShow();

The SlideEngine class serves as a mediator between each slide and the Display object. It is a reusable component. When the startShow() method starts SlideEngine, an internal thread is created and executes the sequence. This thread uses Display.setCurrent() to put a slide on screen and then sleeps for the slide's duration. The procedure repeats until it reaches the end of sequence or endShow() is called. When the sequence ends, the internal thread also terminates. Since the slides are decoupled and a separate yet reusable object (SlideEngine) handles execution, rearranging the slide or sequence has no impact on slide implementation. Each slide can be programmed individually and then joined with other slides.

Don't reinvent the wheel

Design patterns capture development experiences. A well-designed pattern is an effective way to share design knowledge among developers and build structured software. Design patterns, together with their implementations, increase productivity by encouraging developers to build highly maintainable and reusable software or components.

Creating design patterns for J2ME environments takes special consideration. Factors include code size and performance. Many design patterns provide flexible ways to build applications, but they often result in more classes (such as abstract classes) and more complex object hierarchies. However, you can modify design patterns to fit your needs—you might take away some flexibility, but the patterns will still be powerful enough to solve your problems in various scenarios. Your techniques will only improve with experience.

Keep in mind you can always mix and match several patterns in one application. A proper combination of several patterns often creates a more effective pattern. For example, you can use the Slide Show pattern with the Abstract Factory pattern to create a fully content-driven slide show application. There are endless design pattern possibilities. Never underestimate the power of patterns in J2ME environments.

Ben Hui has been programming with Java since its inception and has become addicted to consumer device technologies in recent years. Currently, Ben is a mobile technology specialist who develops software for PDAs and mobile devices and is keen on making J2ME technology work in harmony with daily life experiences.

Learn more about this topic