Smokin’ the decorator pattern with Groovy - No Fluff Just Stuff

Smokin’ the decorator pattern with Groovy

Posted by: Andrew Glover on July 28, 2008

decorator
I recently found myself needing to add additional hip behavior to an object that handled feed parsing– i.e. I needed to add a series of filters (such as location and price) to the items being obtained from the feed. Of course, the easiest (and probably the most naive) way to achieve such a goal is to have added a few conditionals to the feed parsing object itself; however, I realized that this particular problem already had an answer to it– the decorator pattern.

A copasetic example of the decorator pattern in use is Java’s IO library– for example, in the Java code below, a FileReader instance is decorated by a BufferedReader instance.

BufferedReader br = new BufferedReader(new FileReader("readme.txt"));

As my friend, David Geary, wrote many years ago, decorating objects, such as with a BufferedReader, essentially forwards

method calls to the objects they decorate…Decorators add functionality either before or after forwarding to the object they decorate..

So in the code above, decorating the FileReader instance with a BufferedReader facilitates “buffering characters so as to provide for the efficient reading of characters” while reading a file.

One key aspect of the decorator pattern, baby, is a reliance on polymorphism; consequently, in normal Java, for example, the decorator object must implement the same interface (or extend some base class) as the object it intends to decorate; consequently,

the Decorator is indistinguishable from the [hip] object that it contains. That is, a Decorator is a concrete instance of the abstract class, and thus is indistinguishable from any other concrete instance, including other decorators. This can be used to great advantage, as you can recursively nest decorators without any other objects being able to tell the difference, allowing a near infinite amount of customization.

Indeed, the indistinguishable nature of objects facilitated via polymorphism is fundamental to a cornucopia of patterns. And with Groovy, polymorphic behavior can be achieved more easily; that is, patterns that rely on polymorphism can be realized without class hierarchies.

For instance, the original object that required additional behavior is a normal class defined in Groovy:

class FeedReader {

 def readFeed(interestItem, feed, lastUpdateTime) {
  def input = new SyndFeedInput()
  def mefeed = input.build(new XmlReader(feed.toURL()))
  def lstdate = mefeed.entries[0].publishedDate as Date

  def feeditems = []

  if (lstdate.after(lastUpdateTime)) {
    mefeed.entries.each { entry ->
     if (entry.publishedDate.after(lastUpdateTime)) {
      feeditems << new FeedItem(item: interestItem,
        title: entry.title, link: entry.link,
        description: entry.description.value,
        publishedDate: entry.publishedDate)
      }
    }
   }
  return feeditems
 }
}

This class defines one method, readFeed, that reads an RSS/Atom feed using ROME and every item added since the last time the feed was parsed is added to a collection and consequently returned to the caller. As I noted earlier, one could simply add another set of conditionals to the closure to check for, say, the price and location of an item before adding it to the collection; however, a more extensible solution is to apply the decorator pattern and thus decorate the FeedReader.

For instance, in the case of filtering on the price of an item (which, by the way, is dynamically determined based upon the entry’s title), all I had to do was to create a new trippin’ class, in Groovy, that merely contains a method with the same signature:

class PriceFilter {
 private def feedReader
 private int maxPrice

 public PriceFilter(feedRdr, price) {
   this.feedReader = feedRdr
   this.maxPrice = price
 }

 def readFeed(interestItem, feed, lastUpdateTime) {
   def items = this.feedReader.readFeed(interestItem, feed, lastUpdateTime)
   def filteredItems = []
   items.each {item ->
    int iprice = item.getPrice().toInteger()
     if (iprice <= this.maxPrice) {
      filteredItems << item
     }
    }
  return filteredItems
 }
}

Note how the PriceFilter class also has a readFeed method and that that method first defers to an instance, such as FeedReader, and then decorates the result– that is, the PriceFilter class checks each object returned and compares prices. Note too, that I’ve defined a constructor that takes an instance of some object that ideally has a readFeed method– this object isn’t tied to a FeedReader or an interface– it is only tied via the method contract.

Groovy purists will probably bark at me for defining a constructor– indeed, had I dropped the private moniker on the class’s instance variables, a constructor would have been generated for me. In this case, because it’s my bag, old habits never die and I purposely made those instance variables private and thus am forcing clients to properly initialize the object for proper usage.

As you can see, Groovy’s dynamic typing permits me to arbitrarily decorate objects– all that I need to do is ensure decorators have the same method. Then by leveraging constructors, one can easily chain instances like so:

def priceFilter = new PriceFilter(new LocationFilter(mock, locs), 20)

In the code aboe, two filters are applied to the original FeedReader, which, in this case, is actually a mock object that simply has a readFeed method! By the way, this sort of sans-interface polymorphism isn’t limited to Groovy only– the original FeedReader class could have easily been defined in normal Java. Plus, this sort of voodoo polymorphicness can be easily achieved in Ruby, JRuby, Python, and Jython to name a few.

Groovy definitely makes it easier to implement fundamental design patterns by enabling you to leave out the standard scaffolding; what’s more, ubiquitous polymorphism via signatures rather than hierarchies makes testing a whole lot easier! Think about it for a second– my FeedReader instance requires a feed to parse! But I can almost effortlessly mock it by creating an object that responds to a readFeed method. That’s it! Is that smokin’ or what, baby?

Have a listen to JavaWorld's Java Technology Insider

Andrew Glover

About Andrew Glover

Andrew is the Engineering Manager for Netflix's Delivery Engineering Team. He and his team are building the next generation Continuous Delivery platform that is facilitating Netflix's rapid global expansion. Before joining Netflix, he served as the CTO of App47, where he lead the development of a SaaS Mobile Application Management platform. Andrew is also the co-author of Addison Wesley's “Continuous Integration” and he actively blogs about software at thediscoblog.com.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »