Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Evolve your apps with the Phased Process pattern

Evolve your apps with the Phased Process pattern

Tutorial Details:

Evolve your apps with the Phased Process pattern
Evolve your apps with the Phased Process pattern
By: By Jon Benton
Phased Process decouples sequential operations and provides a flexible dispatch mechanism
n situations where a set of operations must proceed in an orderly fashion, you have at your disposal several tried-and-true solutions. The inexperienced programmer might code each operation so that it calls the next operation, similar to a one-way linked list. While this approach works, it is brittle because it requires each operation to know about the next.
Alternatively, depending on the problem being solved, you might apply the State pattern, as described in Design Patterns . The State pattern tailors to objects that must alter their own behavior when their internal state changes. However, when you have an object controlling other, separate objects and want to keep them loosely coupled yet allow them to transfer control to one another, you need a different solution. One battle-tested pattern that addresses these requirements is the Phased Process pattern.
The Phased Process pattern is especially useful because it:
Decouples sequential operations
Unifies the API for phased processes
Provides a flexible dispatch mechanism
And that's what you'll learn more about in this article.
Process in phases
We've all seen installation wizards, those programs that progressively walk you through license acceptance, option selection, and so on before finally installing software on your computer. This is a great example of a phased process: each dialog box in the wizard represents one phase of the installation process.
The Phased Process pattern uses a dispatching mechanism that knows about all the phases and executes them successively. Because the logic for transition between phases is concentrated in the dispatcher, each phase is required to know little, if anything, about any other phase. This modularity is especially nice when, as so often happens in development, the application design changes and you must modify the number or order of phases.
Further, with this pattern, you can simply insert logic at transition points and provide more advanced mechanisms for navigating through a phase set. For example, providing a Previous button so the user can revisit the last executed phase is a trivial exercise, as is providing a Finish button that completes the process by using default values.
Motivation behind the pattern
Phased Process differs from the State pattern in that it controls ordered execution of disparate classes, rather than simply changing its own behavior when its state changes. Phased Process is narrower in scope and targeted at precisely those operation types discussed above: sequential synchronous processes.
This pattern is motivated by the need for a consistent and workable solution to problems that require successive operation of disparate objects. Phased Process provides a uniform API for execution and transition of ordered process phases. Robust implementations allow out-of-order processing, backwards motion through phases, complete cancellation with no side effects, and early successful termination.
The key notion is that you can change the phase, or operation state, through a uniform transition mechanism. The execution of the current phase is likewise presented in a uniform manner. Concentrating phase transition logic into one class increases clarity, illustrates intention, and reduces maintenance.
When to use it
You might apply the Phased Process pattern when a series of synchronous operations must be performed and you want to isolate those operations from each other, perhaps to simplify reordering operations or the later integration of new operations. Typical examples include game leveling, where completing one game phase moves you to the next; those ubiquitous installation wizards; and escalating the severity of user alerts from beeps to double beeps, and from status-bar notes to modal alert messages.
This pattern's benefits flow from how it partitions each phase's behavior and knowledge from the behavior and knowledge of all other phases. The deliberate and explicit concentration of transition logic and the simple and direct API addressing the fundamental aspects of phased process operation are also key benefits. These do not come at the price of flexibility, which, as you'll see, is built into the framework presented here.
A simple implementation
Several variants of this design are possible. The simplest variant -- as Figure 1's FontPicker application demonstrates -- ratchets through an ordered set of phases. FontPicker's user interface (UI) is fairly irritating; few developers would choose to force their users through several dialogs just to specify a font. However, it does illustrate a simple phased process very well.
When you run the FontPicker program (see Resources to download the source code for all sample programs in this article), notice the buttons that let you step through the phases: Previous and Next.
Figure 1. Font color selection dialog
Also notice the Cancel button, which halts the process without side effects. Clearly, this UI is only useful in situations where the user must step through each and every phase or cancel the operation completely.
A more complex program I'll present later uses a more useful framework: it implements Finish and Previous buttons. However, to illustrate a simple phased process, the FontPicker program's one-way incremental approach shows the fundamental control structure and is the basis for more elaborate implementations.
The heart of this phased process resides in the FontSelectProcess class, and the heart of that class is the performCurrentPhase() method:
public void performCurrentPhase() {
switch ( currentPhase ) {
case PHASE_LOAD_ALL_FONTS:
// ... housekeeping code omitted ...
break;
case PHASE_PICK_FONT:
showNewFrame(new PickFont(this, parameters));
break;
case PHASE_COLOR:
showNewFrame(new PickColor(this, parameters));
break;
case PHASE_STYLE:
showNewFrame(new PickStyle(this, parameters));
break;
case PHASE_SIZE:
showNewFrame(new PickSize(this, parameters));
break;
default:
System.out.println("Error: performCurrentPhase: Unknown phase: "
+ currentPhase);
}
}
Even if you haven't run the program, you can tell at a glance what phases are available and the order in which they're likely to occur. Changing the execution order is a simple operation; you only need to change the code in one class. Likewise, adding or removing phases is straightforward.
You can factor much of a phased-process handler's mechanics into a generic class, making implementing new processes a breeze. FontSelectProcess extends SimpleProcess , which provides some convenience methods -- most important, one that handles phase transitions. It does this using a simple, sleek, and very flexible method called phasedProcessHandler() :
public void phasedProcessHandler(int msg) {
switch(msg) {
case MSG_INIT:
currentPhase = 0;
break;
case MSG_NEXT:
currentPhase++ ;
if (numberOfPhases <= currentPhase) {
// all phases have executed
processFinished();
return;
}
break;
case MSG_PREV:
if (0 < currentPhase) {
currentPhase-- ;
} else {
System.out.println("Hey - don't let user go"
+ "back beyond first phase!");
}
break;
case MSG_CANCEL:
// bail out of the process - return here so we
// don't execute performCurrentPhase
processCancelled();
return; // <-- note: return
default:
System.out.println("Error: advanceCurStage: Unknown msg: "
+ msg);
break; // default
}
performCurrentPhase();
}
You use the currentPhase variable to track which phase is currently executing. On phase transitions, this value is modified to reflect the new phase. The phasedProcessHandler() method sets currentPhase to the next executed phase. Since my phases are numbered sequentially from zero upwards, I can simply increment or decrement currentPhase to move forward or backward one step. Finally, the code calls performCurrentPhase() , a method that in the font-picking subclass executes the desired phase.
Who calls the phasedProcessHandler() ? In general, the user does, by pressing the Next, Previous, or Cancel buttons provided by each dialog's UI. Since these controls are ubiquitous, you can use subclassing to your advantage and wrap up the UI in one place.
In this case, all interface dialogs are built from an abstract class called SimpleFrame , an extension of the JInternalFrame class. SimpleFrame provides the common interface components and logic for interacting with SimpleProcess .
When the user presses the Next button, SimpleFrame automatically executes this method:
protected void nextPressed() {
if ( ! validateData() )
return;
saveData();
setVisible(false);
dispatcher.phasedProcessHandler(SimpleProcess.MSG_NEXT);
}
SimpleFrame provides a simple data validation framework useful in contexts where the user can enter invalid values. While this is over-engineered for this particular program, it is worthwhile to consider that future enhancements will likely require some sort of validation. Having an integrated, uniform approach for data validation is worth the extra effort.
As you can see, the nextPressed() method calls validateData() , another method in SimpleFrame . The abstract implementation simply returns true , though subclassers will generally extract the user's entries from the UI and test those values for validity. If any data is invalid, the program should inform the user (possibly by using a convenience SimpleFrame method called badDataAlert() ) and return false to the caller. Should the data be invalid, the nextPressed() method prevents the next phase from executing, letting the user correct the data or cancel. If the data is deemed valid, saveData() is called, allowing subclasses to properly store the data. The Lissajou program's implementation provides a fleshed-out example of the validation framework in action.
Flexible phases


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Evolve your apps with the Phased Process pattern

View Tutorial:
Evolve your apps with the Phased Process pattern

Related Tutorials:

Accelerate your Java apps! - JavaWorld - September 1998
Accelerate your Java apps! - JavaWorld - September 1998
 
What's new in Java Servlet API 2.2? - JavaWorld October 1999
What's new in Java Servlet API 2.2? - JavaWorld October 1999
 
Tcl your Java apps - JavaWorld March 2001
Tcl your Java apps - JavaWorld March 2001
 
Breathe intelligence into Java - JavaWorld April 2001
Breathe intelligence into Java - JavaWorld April 2001
 
Create email-based apps with JAMES
Create email-based apps with JAMES
 
Take control with the Proxy design pattern
Take control with the Proxy design pattern
 
Evolve your apps with the Phased Process pattern
Evolve your apps with the Phased Process pattern
 
Design patterns make for better J2EE apps
Design patterns make for better J2EE apps
 
Repair invalid cached services in the Service Locator pattern
Repair invalid cached services in the Service Locator pattern
 
J2SE 1.4 breathes new life into the CORBA community, Part 3
J2SE 1.4 breathes new life into the CORBA community, Part 3
 
Effort on the edge, Part 1
Effort on the edge, Part 1
 
A first look at JavaServer Faces, Part 2
A first look at JavaServer Faces, Part 2
 
Worth reading
Worth reading
 
good design pattern
good design pattern
 
Data Models for Desktop Apps
Data Models for Desktop Apps This is the third article in a series that presents the prototype of a Java desktop application called JImaging. The first article described the three major Java GUI toolkits: AWT, Swing, and SWT. In the second article, I int
 
Tuning garbage collection in the HotSpot JVM
Packing 100 megabytes of garbage into a 50 megabyte bag.
 
Clean Up Your Mess: Managing Temp Files in Java Apps
Clean Up Your Mess: Managing Temp Files in Java Apps Creating and managing temporary files in a Java application can be a little tricky due to some open JVM bugs. Develop a workaround with some custom code and a clever design.
 
Manage Database Metadata with POI and Excel
Set up quick and easy database metadata housekeeping with the Java Apache POI libraries and Microsoft Excel.
 
Running Wine on the Sun Java Desktop System, Release 2
A BigAdmin reader describes how to install and use Wine, an open source implementation of the Windows API, on the Sun Java Desktop System, Release 2.
 
BioInformatics Tools
BioInformatics Tools BioInformatics Tools The Bioinformatics tools are the software programs for the saving, retrieving and analysis of Biological data and extracting the information from them. Factors that must be taken into consideration when
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.