XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Design Patterns in XML Applications
by Fabio Arciniegas A. | Pages: 1, 2, 3, 4, 5, 6

Synopsis

Contents

Design Patterns in XML Applications
Command Pattern
Flyweight Pattern
Wrapper Pattern
Iterator Pattern
Bibliography

Command is a behavioral pattern used to encapsulate actions in objects. This is highly useful when you want to keep track of changes made to a model, for example in supporting multi-level "do/undo."

Structure

The following is a class diagram of the command pattern. Slightly different versions of this pattern can be found in the literature, however, I chose to present it in this fashion for clarity.

Command Pattern Structure
Figure 1. Command Pattern Structure

XML Context

Suppose you are building an application that uses the DOM representation of an XML document as its basic data—say a component for displaying vector graphics, or a simple shopping list manager.

The user of your program will perform many operations, like deletions and additions. Since you are using the DOM as your underlying model, these changes will sooner or later translate into calls to removeChild and other DOM-specific calls. However, depending on how you structure your program, these changes can become either a hard-to-maintain, hard-to-extend mess, or an organized, extensible solution. Here is where the command pattern can help.

Let's take the shopping list editor as an example. The user wants to delete, add, and annotate the shopping list, among other operations. You use a GUI, so one option would be to hard-code your menu widgets' member calls to DOM-specific methods. For example, when the user selects the menu item "Insert," call insertChild. This has a number of "advantages":

  • Such code is fast to write.

  • Most GUI builders will "lead" you towards this.

  • It can be soft in terms of resource consumption.

It seems like it could be a real choice, but now you want to add undo/redo support to your program, and serious problems regarding this option become apparent:

  • There seems no easy way to maintain your do/undo list: either you change all your hardcoded widget events to call both the DOM methods and log to some list, or you change your DOM representation to somehow log the changes performed (!)

  • Even if you managed to successfully implement the do/undo lists from the hardcoded widget calls, you would be replicating that logic many times, which is hard to maintain and error-prone.

  • There is no clear indication as to which part of your program will manage the undo logic and how it will do it.

The solution that the command pattern proposes is to encapsulate the changes to the DOM into objects, command objects, each capable of doing (and undoing) a particular action. The collection of command objects will be managed by a certain command manager, capable of holding the queue of executed commands, so the user may undo/redo them.

Example

This example reflects a very common approach to DOM processing using the command pattern. If you will be writing applications using DOM as the underlying data structure representation, you are very likely to find this approach useful.

Command Example Structure
Figure 2. Command Pattern Structure

The figure shows the structure of a typical DOM-oriented application using the command pattern for its message passing. The following is the header file for the base class AbstractCommand, which is the foundation of the example. Please refer to command.zip for the complete example code.

Command Example Header
Figure 3. Command Example Header

#include "heqetDef.h"
#include "Notification.h"
/**
   AbstractCommand is the base class for all commands.
   It provides do/undo operations as well as getDescription and
   getState operations for the easy tracking of the executed commands.
   (quite useful when keeping a menu of last performed operations).
 */

class AbstractCommand 
{
 public:
  /**@name Comparison operators
   * The comparison operators in the base AbstractCommand are
   * provided in order to keep STL usability in the CommandManager
   */
  //@{
  
  /// equality operator
  virtual int operator==();

  /// unequality operator
  virtual int operator!=();

  /// increment operator
  virtual void  operator++();
  //@}

  /**@name Do / Undo methods
   */
  //@{
  
  /// Pure virtual operation that in child classes encapsulates the 
  logic of the change
  virtual Notification do() = 0;

  /// Pure virtual operation that in child classes encapsulates the
  logic of undoing a change
  virtual Notification undo() = 0;

  /** Pure virtual operation that in child classes returns the description 
  of the operation
   * (particularly useful for undo/redo lists presented to the user)
   */
  virtual string getDescription() = 0;
  //@}
};
      

Note that even when this example is written in C++, the main principles (and even the code) can be ported to other languages with ease.

Summary of Common XML Uses

My personal experience shows that the command pattern is especially useful in XML applications when:

  • You have a DOM-based application and need to keep track of the changes made to the data model.

  • You have a DOM-based application and need to keep open the possibility for easy and clean extension of the available commands that can be performed on the data model.

In this section we analyzed Command, a behavioral pattern, in object-model-based XML applications. In the next section, we will see a structural pattern in event-based XML applications, Flyweight.

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow