views:

269

answers:

5

I am going over my design patterns, and one pattern I have yet to seriously use in my coding is the Decorator Pattern.

I understand the pattern, but what I would love to know are some good concrete examples of times in the real world that the decorator pattern is the best/optimal/elegant solution. Specific situations where the need for the decorator pattern is really handy.

Thanks.

+1  A: 

Zend Framework uses the decorator for form elements

Some more info: http://framework.zend.com/manual/en/zend.form.decorators.html

Mike B
Yes I can see how using it for form elements makes sense. I am reading a similar example on the wikipedia page: http://en.wikipedia.org/wiki/Decorator_Pattern
Alex Baranosky
+5  A: 

The decorator pattern is used a lot with streams: you can wrap a stream with a stream to get added functionality. I've seen this with the .Net framework - as far as I know this occurs elsewhere. My favourite is using GZipStream around a FileStream, for added compression.

Charlie Salts
ahh yes, I see, good one.
Alex Baranosky
Similarly, Java streams are just a giant collection of decorators decorating decorators that have decorated something that decorates. My face just melted.
Hooray Im Helping
I thought streams would be a better example than the coffee example in my Head First: Design Patterns book on my desk.
Charlie Salts
+4  A: 

I've recently used the decorator pattern in a web service which uses the following CommandProcessor interface:

public Command receive(Request request);
public Response execute(Command command);
public void respond(Response response);

Basically, the CommandProcessor receives a Request and creates the proper Command, executes the Command and creates the appropriate Response, and sends the Response. When I wanted to add timing and log it, I created a TimerDecorator that used an existing CommandProcessor as its component. The TimerDecorator implements CommandProcessor interface, but just adds timing and then calls its target, which is the real CommandProcessor. Something like this:

public class TimerDecorator implements CommandProcessor {
   private CommandProcessor target;
   private Timer timer;

   public TimerDecorator(CommandProcessor processor) {
      this.target = processor;
      this.timer = new Timer();
   }

   public Command receive(Request request) {
      this.timer.start();
      return this.target.receive(request);
   }

   public Response execute(Command command) {
      return this.target.execute(command);
   }

   public void respond(Response response) {
      this.target.response(response);
      this.timer.stop();
      // log timer
   }

}

So the real CommandProcessor is wrapped inside TimerDecorator, and I can treat TimerDecorator just like the target CommandProcessor, but now timing logic has been added.

Kaleb Brasee
+3  A: 

The Decorator Pattern is used for adding additional functionality to a particular object as opposed to a class of objects. It is easy to add functionality to an entire class of objects by subclassing an object, but it is impossible to extend a single object this way. With the Decorator Pattern, you can add functionality to a single object and leave others like it unmodified.

In Java, a classical example of the decorator pattern is the Java I/O Streams implementation.

FileReader       frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);

The preceding code creates a reader -- lrdr -- that reads from a file and tracks line numbers. Line 1 creates a file reader (frdr), and line 2 adds line-number tracking.

Actually, I'd highly encourage you to look at the Java source code for the Java I/O classes.

Pascal Thivent
+1  A: 

The decorator is simple yet extremely powerful. It is key in achieving separation of concerns and is an essential tool for the Open Closed Principal. Take a common example of placing an order for a product:

IOrderGateway
{
    void PlaceOrder(Order order);
{

Main implementation: AmazonAffiliateOrderGateway

Possible decorators could be:

  • IncrementPerformanceCounterOrderGateway
  • QueueOrderForLaterOnTimeoutOrderGateway
  • EmailOnExceptionOrderGateway
  • InterceptTestOrderAndLogOrderGateway

Take a look here for a more detailed example.

Michael Valenty