Monday, May 2, 2011

Implementing the Decorator pattern using Groovy's @Delegate

Let's say we want to write a decorator around a List to add a creation time to the list. We've all written something like this before, and it usually looks something like:

public class ListDecorator implements List {

private final List delegate;
private final Date creationTime = new Date();

public ListDecorator(List delegate) {
this.delegate = delegate;
}

public Date getCreationTime() { return createTime; }

public void add(...) {
delegate.add(...);
}

public int indexOf(...) {
return delegate.indexOf(...);
}

// wrap all of the list methods
}


This is very tedious, and we still need to write tests to make sure we actually delegated to the right method.

Enter the groovy @Decorator annotation

// notice we don't need to implement the List interface here
// since we can take advantage of duck typing
class GroovyListDecorator
{
// all of the calls to the list methods will be delegated to this list
@Delegate final List delegate

private final Date creationTime = new Date()

GroovyListDecorator(List delegate) {
this.delegate = delegate;
}

Date getCreationTime() {
creationTime
}
}

And now we can use it like this:
def list = new GroovyListDecorator(new LinkedList())
// these methods delegate to the LinkedList delegate
list.add("abc")
list.add("def")
println list.size() // 2
println list.creationTime // Mon May 02 19:49:55 EDT 2011


And it's as easy as that.

3 comments:

  1. Nice explanation about Decorator pattern.

    ReplyDelete
  2. U saved my life ! Thank you.
    I was trying to create a decorator pattern without having to implement all methods and that helped a lot.

    ReplyDelete
  3. Important notice: don't try to use this approach for extending classes (instead of implementing interfaces as in the example above) - it would'nt work. :( However, when using it as in the example above, it works great!

    ReplyDelete