Working with Design Pattern: Decorator

Introduction

I'm interested in building a better email client. Email clients today are not much different than email clients from fifteen years ago! I have a number of interesting ideas that I'd like to build into such an application.

The core of the application is an Email object. The Email class, presented here, is capable of sending an email via SMTP. It requires the JavaMail API and the JavaBeans Activation Framework (JAF), which are distributed in the JARs mail.jar and activation.jar (freely available for download from Sun). It's not the best code I've written, but it works:

To send messages, you'll need to specify a number of configuration properties. Of course, Java gives you many ways to do so. You can set properties programmatically, you can load them from a properties file, or you can pass them to the application via -D command-line arguments to the Java VM. Here are the properties I had to set, using -D, to get the Email class actually working:

If you want to watch the interaction between the JavaMail client and your mail server, you can turn on debug mode:

-Dmail.debug=true

Adding Features

I'd like to add a number of features to the Email class. For example, I'd like to be able to initiate the spell checker when I'm about to send, but only for certain recipients. I'd like to be able to log emails to other recipients. I might want to censor other emails for content. I might like an attachment verifier—something that scans the email for the words "attached" or "attachment," and asks whether I forgot an attachment if one is not provided. I might like auto CCing capabilities for certain emails.

All of these features would be great, at least from my standpoint. I could build them all into my Email class, but that would result in a pretty bloated class, with lots of if statements. I'm also not totally oblivious to the needs of others—many people would want to turn off my pet features. An inheritance hierarchy would certainly be unworkable. What I want is the ability to dynamically specialize email handling—something that the decorator design pattern affords.

Using the Decorator Design Pattern

With an inheritance hieararchy, I would extend from Email and override the send method. Using the decorator pattern instead, I would first define a common interface, perhaps named Sendable, declaring the method send. I'd then build a number of classes implementing this interface. These Sendable implementations would be decorators of the core Email class. Within their implemention of the send method, each decorator would invoke its own special behavior. A decorator also would contain a reference to another Sendable object that it decorated, or wrapped. As part of its implementation of send, the decorator would need to delegate to the contained object's send method.

As usual, it's often easier to see this in code. The first step is to extract an appropriate interface from the Email class: