Thursday, October 16, 2008

Design Patterns (1) - Strategy

book reference:

  1. Gang-of-four: Design Patterns
  2. Head first design patterns

resource reference:

  1. wiki - design pattern
  2. source-making
  3. http://www.dofactory.com/Patterns/Patterns.aspx
  4. http://blog.cumps.be/design-patterns-strategy-pattern/
  5. http://www.patterndepot.com/put/8/JavaPatterns.htm
  6. http://www.codeguru.com/forum/showthread.php?t=327982

Strategy Pattern:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

  • The Context has-a behavior of Strategy, which can be implemented with different algorithms.
  • We define a private member in Context: a pointer to the general superclass Strategy.
  • We have a set_strategy method in Context class to change behavior at runtime.
  • We also have a superclass: Strategy and a bunch of subclass : ConcreteStrategy to implement the behavior.
  • In client code, we have one or multiple instances of Context.
  • At any given time, only one ConcreteStrategy is availabe to be executed a single Context object.

Strategy Pattern example:   

#include <iostream>
image
using namespace std;

class StrategyInterface
{
public:
virtual void execute() = 0;
};

class ConcreteStrategyA: public StrategyInterface
{
public:
virtual void execute()
{
cout << "Called ConcreteStrategyA execute method" << endl;
}
};

class ConcreteStrategyB: public StrategyInterface
{
public:
virtual void execute()
{
cout << "Called ConcreteStrategyB execute method" << endl;
}
};

class ConcreteStrategyC: public StrategyInterface
{
public:
virtual void execute()
{
cout << "Called ConcreteStrategyC execute method" << endl;
}
};

class Context
{
private:
StrategyInterface *_strategy;

public:
Context(StrategyInterface *strategy):_strategy(strategy)
{
}
void set_strategy(StrategyInterface *strategy)
{
_strategy = strategy;
}
void execute()
{
_strategy->execute();
}
};

int main(int argc, char *argv[])
{
ConcreteStrategyA concreteStrategyA;
ConcreteStrategyB concreteStrategyB;
ConcreteStrategyC concreteStrategyC;

Context contextA(&concreteStrategyA);
Context contextB(&concreteStrategyB);
Context contextC(&concreteStrategyC);

contextA.execute();
contextB.execute();
contextC.execute();

contextA.set_strategy(&concreteStrategyB);
contextA.execute();

return 0;
}