Tuesday, October 9, 2007

Strategy and Decorator - A comparison (Part 2)

In my last entry, I talked a bit about the Decorator design pattern and how one can use it to extend the functionality of a class. In part two of my look at the Decorator and Strategy design patterns, I'll take a similar look at the Strategy pattern. (Go figure.)

The Strategy pattern, like Decorator, lets one vary part of a class's functionality dynamically, but in a different way (and for a different purpose). The goal with Strategy is to define an interface for a family of algorithms and allow them to be dynamically substituted. It does this in a very similar way as Decorator, at some level, in that all strategy implementations must conform to an interface that is known to the caller. The important difference is that rather than one object wrapping another up, from a structural point of view, the caller (sometimes called the Context as it is in the Wikipedia article), delegates a single method (usually) to the concrete strategy implementation. That's probably a bad explanation. Let's look at an example.

public interface SortStrategy {
  public String[] sort(String[] items);
}

public class QuickSortStrategy implements SortStrategy {
  public String[] sort(String[] items) {
    // ...
  }
}

public class MyApplication {
  private SortStrategy sortStrategy;

  public void main(String[] args) {
    MyApplication app = new MyApplication();

    app.setSortStrategy(new QuickSortStrategy());

    app.arrayPrinter("Sorted args: " + app.sort(args));
  }

  // Getters, setters, arrayPrinter(), etc...
}

Of course, it's not very interesting when we have just one concrete strategy implementation like in our example, but you can easily see how you can pick a class based on external information. I use sorting as an example because it's dead simple to understand why one would want to vary the algorithm based on the data.

What's really interesting about this is when we start combining a pattern like Strategy with, for instance, generics. Now, you have a situation where you can vary algorithms and types; that's reusability.

When people talk about Strategy, then tend to talk about vary an algorithm, but it's also interesting to consider things that aren't necessarily algorithms. For instance, Strategy is an option when talking about varying serialization methods, network transports, and so forth. If there is a case where you want to vary part of an object's behavior at runtime, but not necessarily all of it (or can't because of other inheritance requirements), Strategy can really bail you out. In short, you're delegating some behavior to a dynamically selected class that is guaranteed to conform to a known interface for implementing said behavior; that's Strategy.

While this hasn't been a direct A / B comparison of Decorator and Strategy, hopefully a better understanding of these two patterns will help you as it has me.

As always, comments are very welcome!

1 comment:

Poker Coach said...

I hope, you will find the correct decision.