DCSIMG
Strategy Pattern - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2011 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

Strategy Pattern

Strategy Pattern

Today I present the strategy pattern.
You can read my previous posts about design patterns here:
Structural patterns
Decorator pattern 
Proxy pattern
Facade pattern
Adapter pattern
Composite pattern
Bridge pattern
Flyweight pattern

Creational patterns
Singleton pattern
Abstract Factory pattern
Prototype pattern
Factory Method pattern
Builder pattern

Strategy Pattern Introduction
The strategy pattern is one of my favorite patterns.
For every problem in development there are many solutions. There are times
that one solution is preferable then another. But sometimes the other algorithm is
preferable. The strategy pattern helps us to divide an algorithm from a host class
and then move it to another class. By doing so the client can choose which
algorithm will be performed in runtime from a set of algorithms that were
implemented earlier.

Use Cases for the Strategy Pattern
Use the strategy pattern in the following situations:

  • There are many classes that differ only in their behavior.
  • There are different algorithms that solve a problem and you
    want to give the client a way to choose between them.
  • The client has no real influence on the algorithms which makes them
    a black box. 

UML Diagram
Strategy Pattern UML 

Example in C#
The following code will explain how to use the strategy pattern:

    #region Strategy

 

    interface IStrategy

    {

        int Sum(List<int> list);

    }

 

    #endregion

 

    #region Concrete Classes

 

    class ConcreteStrategy1 : IStrategy

    {

        #region IStrategy Members

 

        /// <summary>

        /// Calculate the sum of integers in the

        /// given list using LINQ

        /// </summary>

        /// <param name="list">The given integer list</param>

        /// <returns>sum of integers in the list</returns>

        public int Sum(List<int> list)

        {

            return list.Sum();

        }

 

        #endregion

    }

 

    class ConcreteStrategy2 : IStrategy

    {

        #region IStrategy Members

 

        /// <summary>

        /// Calculate the sum of integers in the

        /// given list using standard calculation

        /// </summary>

        /// <param name="list">The given integer list</param>

        /// <returns>sum of integers in the list</returns>

        public int Sum(List<int> list)

        {

            int result = 0;

 

            foreach (int value in list)

            {

                result += value;

            }

 

            return result;

        }

 

        #endregion

    }

 

    #endregion

 

    #region Context

 

    class Context

    {

        #region Members

 

        IStrategy _strategy;

 

        #endregion

 

        #region Ctor

 

        /// <summary>

        /// Construct a new Context object with

        /// the given strategy.

        /// </summary>

        /// <param name="strategy">The given strategy</param>

        public Context(IStrategy strategy)

        {

            _strategy = strategy;

        }

 

        #endregion

 

        #region Methods

 

        public void PerformCalculation(List<int> list)

        {

            Console.WriteLine(string.Format("The list's sum is {0}",

                _strategy.Sum(list)));

        }

 

        #endregion

    }

 

    #endregion

The example is simple I use an interface to define the wanted strategy.
The algorithm I use calculate the sum of an integer list. I built two concrete
classes. One concrete use LINQ for the calculation and the other use standard
array sum. The Context class gets the strategy in its constructor and use it in the
PerformCalculation method. The Context client is responsible to deliver the
relevant strategy. The example is naive but it shows how to use the pattern.

Summary
The strategy pattern is very useful pattern. I use it a lot when I have to
choose from a set of solutions in runtime. The implementation of the
pattern is simple and the gain from it is high.
The next post will explain in details how to use the iterator pattern.

Comments

Mr. Javaman said:

This pattern's power is only apparent once one finally sees that you can actual stop using cascading code techniques.  Did you know that concrete classes of the abstract implementations in this pattern can represent total code isolation?

What does that mean?  If one designs this correct you can add tons of function piecemeal without ever impacting the prior concrete classes.  When you think about the fact that 60% of all software costs (or even more) deal with code maintenence, you can see adding new specs. can become a HUGE deal.  This pattern isoloates changing specifications and allows a developer to affect only areas needing changes.  It's as if you have a source code filter whereby nothing but the concrete class is affected.

If the client code utilizes interfaces and takes them as parms, then you have true encapsulation of what changes.  Plus you have the ability to upcast to the client which allows for even better "commonality" with respect to what is provided to be "worked on".  The concept of contract programming is hardly more apparent than in this important pattern.  

Ahh, can you tell the light went off for me on this one?

# October 15, 2008 7:59 AM

Gil Fink on .Net said:

Applying Strategy Pattern Instead of Using Switch Statements Once in a while I’m stumbling on switch

# November 22, 2009 9:53 AM