October 21, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Pattern Summaries: Facade and Iterator

  • September 26, 2003
  • By Mark Grand
  • Send Email »
  • More Articles »

The essence of a pattern is a reusable solution for a recurring problem. A complete pattern will also provide reasons to use and not use the solution, the consequences of using the solution and suggestions on how to implement the solution. The summaries in these articles will just describe the essential problem and its solution.

This and the next few articles will be focused on patterns related to the low-level structure of the classes in an application. This article discusses two patterns called Façade and Iterator, which come from Volume 1 of "Patterns in Java."

Façade

Consider the organization of classes to support the creation and sending of e-mail messages. The classes may include the following:

  • A MessageBody class whose instances will contain message bodies.
  • An Attachment class whose instances will contain message attachments that can be attached to a MessageBody object.
  • A MessageHeader class whose instances will contain header information (to, from, subject...) for an e-mail message.
  • A Message class whose instances will tie together a MessageHeader object and a MessageBody object.
  • A Security class whose instances can be used to add a digital signature to a message.
  • A MessageSender class whose instances are responsible for sending Message objects to a server that is responsible for delivering the e-mail to its destination or another server.

Figure 1 is a class diagram showing the relationships between these classes and a client class:


Figure 1. E-Mail creation.

As you can see, working with these e-mail classes adds complexity to a client class. To use these classes, a client must know of at least these six of them, the relationship between them and the order in which it must create instances of the classes. If every client of these classes must take on this additional complexity, it makes the e-mail classes more difficult to reuse.

The Façade pattern is a way to shield clients of classes like the e-mail classes from the complexity of using those classes. It works by providing an additional reusable object that hides most of the complexity of working with the other classes from client classes. Figure 2 is a class diagram showing this more reusable organization.


Figure 2. Reusable e-mail creation.

In this new scheme, the portion of the Client class that was responsible for interacting with the e-mail classes has been refactored into a separate reusable class. Client classes now need only be aware of the MessageCreator class. Furthermore, the internal logic of the MessageCreator class can shield client classes from having to create the parts of an e-mail message in any particular order.

Figure 3 shows the general structure of the Façade pattern.


Figure 3. The Façade pattern.

The client object interacts with a Facade object that provides necessary functionality by interacting with the rest of the objects. If there is some additional functionality that is only needed by some clients, then instead of providing it directly, the Facade object may provide a method to access another object that does provide the functionality.

Below is code for the MessageCreator class shown in Figure 2. Instances of MessageCreator class are used to create and send e-mail messages. It is shown here as a typical example of a Façade class.

public class MessageCreator {
    // Constants to indicate the type of message to create
    public final static int MIME = 1;
    public final static int MAPI = 2;
...
    private Hashtable headerFields = new Hashtable();
    private RichText messageBody;
    private Vector attachments = new Vector();
    private boolean signMessage;

    public MessageCreator(String to, String from, String subject) {
        this(to, from , subject, inferMessageType(to));
    } // Constructor(String, String, String)

    public MessageCreator(String to, String from, String subject, int type) {
        headerFields.put("to", to);
        headerFields.put("from", from);
        headerFields.put("subject", subject);
        //...
    } // Constructor(String, String, String, int)

    /**
     * Set the contents of the message body.
     */
    public void setMessageBody(String messageBody) {
        setMessageBody(new RichTextString(messageBody));
    } // setMessageBody(String)

    /**
     * Set the contents of the message body.
     */
    public void setMessageBody(RichText messageBody) {
        this.messageBody = messageBody;
    } // setMessageBody(RichText)

    /**
     * Add an attachement to the message
     */
    public void addAttachment(Object attachment) {
        attachments.addElement(attachment);
    } // addAttachment(Object)

    /**
     * Set whether this message should be signed.  The default is false.
     */
    public void setSignMessage(boolean signFlag) {
        signMessage = signFlag;
    } // setSignMessage(boolean)

    /**
     * Set the value of a header field.
     */
    public void setHeaderField(String name, String value) {
        headerFields.put(name.toLowerCase(), value);
    } // setHeaderField(String, String)

    /**
     * Send the message.
     */
    public void send() {
        ...
    } // send()

    /**
     * Infer an message type from a destination e-mail address.
     */
    private static int inferMessageType(String address) {
        int type = 0;
...
        return type;
    } // inferMessageType(String)

    /**
     * Create a Security object appropriate for signing this message.
     */
    private Security createSecurity() {
        Security s = null;
...
        return s;
    } // createSecurity()

    /**
     * Create a MessageSender object appropriate for the type of
     * message being sent.
     */
    private void createMessageSender(Message msg) {
...
    } // createMessageSender(Message)
...
} // class MessageCreator
The Façade pattern places no demands on the classes that the Façade class uses. Since they contain nothing that contributes to the Façade pattern their code is not shown.

Iterator

Suppose you are writing classes to allow someone to browse inventory in a warehouse. There will be a user interface that allows a user to see the description, quantity on hand, location and other information about each inventory item.

The inventory browsing classes will be part of a customizable application. For this reason, they must be independent of the actual class that provides the collections of inventory items. To provide this independence, you design an interface that allows the user interface to sequentially access a collection of inventory items without having to be aware of the actual collection class being used. The class diagram in Figure 4 shows the relevant part of the design.


Figure 4. Inventory Iterator.

In Figure 4, the user interface classes that that constitute the inventory browser are shown as the composite class InventoryBrowser. An instance of the InventoryBrowser class is asked to display InventoryItem objects in the collection encapsulated by an InventoryCollection object. The InventoryBrowser object does not directly access the InventoryCollection object. Instead, it is given an object that implements the InventoryIteratorIF interface. The InventoryIteratorIF interface defines methods to allow an object to sequentially fetch the contents of a collection of InventoryItem objects.

Now we will take a look at what the Iterator pattern looks like in the general case. The class diagram in Figure 5 shows the organization of the classes and interfaces that participate in the Iterator pattern.


Figure 5. The Iterator pattern.

Here are descriptions of the roles that classes and interfaces play in the organization shown in Figure 5:

Collection
A class in this role encapsulates a collection of objects or values.
IteratorIF
An interface in this role defines methods to sequentially access the objects that are encapsulated by a Collection object.
Iterator
A class in this role implements an IteratorIF interface. Its instances provide sequential access to the contents of the Collection object associated with the Iterator object.
CollectionIF
Collection classes normally take responsibility for creating their own iterator objects. It is convenient to have a consistent way ask a Collection object to create an Iterator object for itself. To provide that consistency, all Collection classes implement a CollectionIF interface that declares a method for creating Iterator objects.

We end this discussion of the Iterator pattern with some code based on the example at the beginning of the discussion. Here is a listing of the InventoryIteratorIF interface.

public interface InventoryIteratorIF {
    public boolean hasNextInventoryItem() ;
    public InventoryItem getNextInventoryItem() ;
    public boolean hasPrevInventoryItem() ;
    public InventoryItem getPrevInventoryItem() ;
} // interface InventoryIterator

Below is a skeletal listing of the InventoryCollection class. The listing includes the Iterator method that other classes will use to get an object to iterate over the contents of an InventoryCollection object. It also includes the private class that the iterator method instantiates.

public class InventoryCollection {
    ...
    public InventoryIteratorIF iterator() {
        return new InventoryIterator();
    } // iterator()

    private class InventoryIterator implements InventoryIteratorIF {
        public boolean hasNextInventoryItem() {
            ...
        } // hasNextInventoryItem()

        public InventoryItem getNextInventoryItem() {
            ...
        } // getNextInventoryItem()

        public boolean hasPrevInventoryItem() {
            ...
        } // hasPrevInventoryItem()

        public InventoryItem getPrevInventoryItem() {
            ...
        } // getPrevInventoryItem()
    } // class InventoryIterator
    ...
}
 

About the Author

Mark Grand is the author of a series of books titled "Patterns in Java." He is a consultant who specializes in object-oriented design and Java. He is currently working on a framework to create integrated enterprise applications.






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel