Bak 2 Basiks – Design Patterns – The Strategy Pattern

Design patterns are an ever growing collection of tried and tested best practices for implementing software code.  No matter if your language of choice is C#, Java, C++, or Visual Basic, design patterns present blue prints for development of common object oriented principles. 

Most developers have heard of design patterns, some have used them in different development scenarios, some theorize about them, few people use them continuously in their day-to-day development.  Why?

Even though design patterns exist to make the life of a software developer/programmer easier, they present a learning curve for those not practiced in this area.  The problem with patterns is that there exist so many of them.  Speak to a any talented software developer and ask him/her about design patterns and they’ll probably quote the “Singleton,” “Model View Controller,” “Command,” or “Observer” patterns because these are most common, but many more patterns exist.  Microsoft has reams of online documentation dedicated to patterns, and the Java SDK is built atop of a series of the best used patterns.  So it is no surprise that software developers not practiced in the area shy away from design patterns and stick to traditional ad-hoc methods of software architecture and implementation. 

So, this series of posts is aimed at describing the most common patterns that any well designed software creation is not without.  This first post in the series descries the “Strategy Pattern”…

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.

In English – this pattern describes a way to abstract out most commonly changing code from code that never changes and encapsulate this commonly changing code so that it can be used or interchanged with other similar code to provide behavior like functionality.

An example:

Let’s assume we have an application that wants to model birds. A base class exists that defines the common attributes of all birds:

class Bird
{
  fly()
}

The fly method provides the method for making our bird fly..but not all birds fly, so our Ostridge throws a NoFly exception.

So, now we have a base bird class, an Ostridge class, and we can implement many more derived bird type classes.  What happens when we want to add a new behavior to our birds, such as “canSwim()”?  This would involve adding an abstract (or virtual) method to the base class and then implementing the same method in all derived classes, but what if we had lots of bird classifications?

Enter the strategy pattern..

Abstract out the code that changes, which in this case is anything behavior related to birds…

interface BirdBehavior
{
  fly()
  canSwim()
}

Implement a series of common behavior types common to groups of birds…

class NoSwimorFly : BirdBehavor { … }
class FlyNoSwim : BirdBehavior { … }
class FlyAndSwim : BirdBehavior { … }

Now assign a bird behavior to bird instance classes…

class Bird
{
    Display(Behavior b)
    {
      b.fly();
      b.canSwim();
    }
}

So, now when a behavior of a bird changes we only need to change the few classification groups and not the large list of birds in our avery application.