Tuesday, August 13, 2013

Design Pattern: Strategy

Design patterns are an excellent way of making sure your object-oriented code is easily maintainable.  And, since we're all on an endless quest of knowledge I thought it would be beneficial for you, the reader, as well as for me, to go over some design patterns.  To begin we'll look at the Strategy pattern.
Strategy Design Pattern: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.
Note:  In order to keep this article short I haven't embedded any code into the explanations.  Instead, I've added links to the relevant pieces of code.  However, all of the code is on Github. Feel free to fork it and build your own examples, since that really is the best way to learn.

Design Principles

There are also a couple of important design principles that are used in this pattern.
  1. Program to an interface, not an implementation
    • This means don't pass concrete implementations around, but use the abstractions like the parent class or interface. 
    • For example, the constructor in our FlowerContext class, public FlowerContext(FlowerStrategy flowerStrategy) takes a FlowerStrategy, an interface, not a Daisy, HoneySuckle, or Rose; concrete implementations.
  2. Favor composition over inheritance
    • It is better to declare a behavior as a property instead of inheriting it.  It's easier to think of it as a has-a relationship, instead of a is-a.
    • Again, lets look at our FlowerContext class.  The FlowerContext has a FlowerStrategy that can be modified at run-time.  When we need to add a new flower we can add a new flower that has no effect whatsoever on the existing flowers.  

Strategy Pattern

Sometimes a nice class diagram helps to explain things better than a wordy explanation can.  And, lacking that, we'll make a shoddy one. 

The FlowerContext  has a custom behavior that comes in the form of FlowerStrategy.  FlowerStrategy itself is not a class we can instantiate (new FlowerStrategy() is not allowed) so we create our concrete implementations.  In this example we are only implementing a description and setting a name.

The FlowerStrategy delegates to its subclasses the behavior that should be performed while FlowerContext doesn't really care what behavior is being done because it knows it has a getName() method from FlowerStrategy as well as an implemented getDescription() that the concrete classes have implemented.

Ok, here is the code

Well, in order to make things easier for you I've embedded the code here for your viewing pleasure.  

Interfaces Concrete Implementations The Client
When RunMe is executed this is the output:
Daisy A small grassland plant (family Compositae) that has flowers with a yellow disk and white rays. HoneySuckle A widely distributed climbing shrub (genera Lonicera and Diervilla) with tubular flowers that are typically fragrant and of two colors Rose A prickly bush or shrub (genus Rosa) that typically bears red, pink, yellow, or white fragrant flowers, native to north temperate
But you don't need to take my word for it, clone or download the repo and run mvn exec:java inside the project directory (see Maven if you're not familiar with the mvn command), or you can import it into your favorite IDE like eclipse.

Remember to fork the repo and create your own Strategy pattern.

Additional Reading

If this is a new concept chances are you'll need to hear it a few more times before it sinks in so here are some good resources.
Or, here are some books that I've found useful for understanding design patterns in general.

No comments:

Post a Comment