Wednesday, November 4, 2009

Facade




















Chapter 7 -
Structural Patterns
Patterns in Java, Volume 1: A Catalog of Reusable Design Patterns Illustrated with UML, Second Edition
by Mark Grand
John Wiley & Sons � 2002



























Façade



This pattern was previously described in [GoF95].




Synopsis


The Façade pattern simplifies access to a related set of objects by providing one object that all objects outside the set use to communicate with the set.






Context


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


























l



A MessageBody class whose instances will contain message bodies




l



An Attachment class whose instances will contain message attachments that can be attached to a MessageBody object




l



A MessageHeader class whose instances will contain header information (to, from, subject, etc.) for an email message




l



A Message class whose instances will tie together a MessageHeader object and a MessageBody object




l



A Security class whose instances can be used to add a digital signature to a message




l



A MessageSender class whose instances are responsible for sending Message objects to a server that is responsible for delivering the email to its destination or to another server





Figure 7.10 is a class diagram showing the relationships between these classes and a client class.






Figure 7.10: Email creation

As you can see, working with these email classes adds complexity to a client class. To use these classes, a client must know of at least these six of them, the relationships 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 email classes more difficult to reuse.


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






Figure 7.11: Reusable email creation.

In this new scheme, the portion of the Client class that was responsible for interacting with the email 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 email message in any particular order.






Forces

















J



There are many dependencies between classes that implement an abstraction and their client classes. The dependencies add noticeable complexity to clients.




J



You want to simplify the client classes, because simpler classes result in fewer bugs. Simpler clients also mean that less work is required to reuse the classes that implement the abstraction.




J



You are designing classes to function in cleanly separated layers. You want to minimize the number of classes that are visible from one layer to the next.








Solution



Figure 7.12 is a class diagram showing the general structure of the Façade pattern. The client object interacts with a Façade object that provides necessary functionality by interacting with the rest of the objects. If there is some additional functionality that is needed by only some clients, then instead of providing it directly, the Façade object may provide a method to access another object that does provide the functionality.






Figure 7.12: Façade pattern.

It is not necessary for a Façade class to act as an impenetrable barrier separating client classes from the classes that implement an abstraction. It is sufficient, and sometimes better, for a Façade class to merely be a default way of accessing the functionality of the classes that implement an abstraction. If some clients need to directly access abstraction-implementing classes, then the Façade class should facilitate this with a method that returns a reference to the appropriate implementation object.


The point of the Façade class is to allow simple clients, not require them.






Implementation


A Façade class should provide a way for client objects to obtain a direct reference to an instance of abstraction-implementing classes that client objects may need to know about. However, there may be some abstraction-implementing classes that client classes have no legitimate reason to know about. The Façade class should hide these classes from client classes. One way to do that is to make these classes private inner classes of the Façade class.


Sometimes you want to vary the implementation classes that a façade object uses to accommodate variations on the abstraction being implemented. For example, returning to the email example under the Context heading, you may need a different set of classes to create MIME-, MAPI-, or Notes-compliant messages. Different sets of implementation classes usually require different Façade classes. You can hide the use of different Façade classes from client classes by applying the Interface pattern. Define an interface that all Façade classes for email creation must implement. Have client classes access the Façade class through an interface rather than directly.






Consequences














J



Interposing a façade class between the classes that implement an abstraction and their clients simplifies client classes by moving dependencies from client classes to the façade class. Clients of façade objects do not need to know about any of the classes behind the façade.




J



Because the Façade pattern reduces or eliminates the coupling between a client class and the classes that implement an abstraction, it may be possible to change the classes that implement the abstraction without any impact on the client class.








Java API Usage



The java.net URL class is an example of the Façade pattern. It provides access to the contents of URLs. A class can be a client of the URL class and use it to get the contents of a URL without being aware of the many classes that operate behind the façade provided by the URL class. On the other hand, to send data to a URL, the client of a URL object may call its openConnection method, which returns the URLConnection object that the URL object uses.






Code Example


The following is code for the MessageCreator class shown in the class diagram under the Context heading. Instances of the MessageCreator class are used to create and send email 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 attachment 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 a message type from a destination email 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.






Related Patterns



Interface.  The Interface pattern can be used with the Façade pattern to allow different façade classes to be used without client classes being aware of the different classes.



Law of Demeter.  A conceptual model that uses the Law of Demeter pattern (described in Patterns in Java, Volume 2) often gives rise to a design that follows the Façade pattern.



Adapter.  The Adapter pattern is used to allow client classes to treat a single object that does not implement an interface as an object that does implement the interface. The Façade pattern can be used to allow client classes to treat a group of objects as a single object that implements a particular interface.



Pure Fabrication.  The design of a façade class is an application of the Pure Fabrication pattern described in Patterns in Java, Volume 2.


















No comments: