Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Strategy (Design Pattern)

 

The Strategy Design Pattern 'defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from the clients that use it' [1].

 

 

 

 

 

Example from 'Head First Design Patterns' [1]

 

'Head First Design Patterns' [1] gives an example of a Strategy. But, this book uses Java as its programming language. I have done my best to convert it to C++ in a correct way, with the least changes possible.

 

 

The code consists out of four units:

 

Both the FlyBehavior and QuackBehavior are Strategies.

 

 

 

 

 

UnitDuck.h

 

//---------------------------------------------------------------------------
#ifndef UnitDuckH
#define UnitDuckH
//---------------------------------------------------------------------------
#include <boost/shared_ptr.hpp>
struct QuackBehavior;
struct FlyBehavior;
//---------------------------------------------------------------------------
struct Duck
{
  virtual void display() const = 0;
  void performFly() const;
  void performQuack() const;
  void swim() const;
  void setFlyBehavior(boost::shared_ptr<FlyBehavior> fb);
  void setQuackBehavior(boost::shared_ptr<QuackBehavior> qb);
 
  protected:
  boost::shared_ptr<QuackBehavior> quackBehavior;
  boost::shared_ptr<FlyBehavior> flyBehavior;
  ~Duck() {} //All ABC's must have a virtual destructor
};
//---------------------------------------------------------------------------
struct MallardDuck : public Duck
{
  MallardDuck();
  void display() const;
};
//---------------------------------------------------------------------------
struct RubberDuck : public Duck
{
  RubberDuck();
  void display() const;
};
//---------------------------------------------------------------------------
struct ModelDuck : public Duck
{
  ModelDuck();
  void display() const;
};
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitDuck.cpp

 

//---------------------------------------------------------------------------
#include <cassert>
#include <iostream>
#include "UnitDuck.h"
#include "UnitFlyBehavior.h"
#include "UnitQuackBehavior.h"
//---------------------------------------------------------------------------
void Duck::performFly() const
{
  assert(flyBehavior);
  flyBehavior->fly();
}
//---------------------------------------------------------------------------
void Duck::performQuack() const
{
  assert(quackBehavior);
  quackBehavior->quack();
}
//---------------------------------------------------------------------------
void Duck::swim() const
{
  std::cout << "All ducks float, even decoys!\n";
}
//---------------------------------------------------------------------------
void Duck::setFlyBehavior(boost::shared_ptr<FlyBehavior> fb)
{
  flyBehavior = fb;
}
//---------------------------------------------------------------------------
void Duck::setQuackBehavior(boost::shared_ptr<QuackBehavior> qb)
{
  quackBehavior = qb;
}
//---------------------------------------------------------------------------
MallardDuck::MallardDuck()
{
  flyBehavior.reset(new FlyWithWings);
  quackBehavior.reset(new Quack);
}
//---------------------------------------------------------------------------
void MallardDuck::display() const
{
  std::cout << "I'm a real mallard duck\n";
}
//---------------------------------------------------------------------------
RubberDuck::RubberDuck()
{
  flyBehavior.reset(new FlyNoWay);
  quackBehavior.reset(new Squeak);
}
//---------------------------------------------------------------------------
void RubberDuck::display() const
{
  std::cout << "I'm a rubber duck\n";
}
//---------------------------------------------------------------------------
ModelDuck::ModelDuck()
{
  flyBehavior.reset(new FlyNoWay);
  quackBehavior.reset(new MuteQuack);
}
//---------------------------------------------------------------------------
void ModelDuck::display() const
{
  std::cout << "I'm a model duck\n";
}

 

 

 

 

 

UnitFlyBehavior.h

 

//---------------------------------------------------------------------------
#ifndef UnitFlyBehaviorH
#define UnitFlyBehaviorH
//---------------------------------------------------------------------------
struct FlyBehavior
{
  virtual void fly() const = 0;
  virtual ~FlyBehavior() {} //All ABC's must have a virtual destructor
};
//---------------------------------------------------------------------------
struct FlyWithWings : public FlyBehavior
{
  void fly() const;
};
//---------------------------------------------------------------------------
struct FlyNoWay : public FlyBehavior
{
  void fly() const;
};
//---------------------------------------------------------------------------
struct FlyRocketPowered : public FlyBehavior
{
  void fly() const;
};
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitFlyBehavior.cpp

 

//---------------------------------------------------------------------------
#include <iostream>
#include "UnitFlyBehavior.h"
//---------------------------------------------------------------------------
void FlyWithWings::fly() const
{
  std::cout << "I'm flying!!\n";
}
//---------------------------------------------------------------------------
void FlyNoWay::fly() const
{
  std::cout << "I can't fly\n";
}
//---------------------------------------------------------------------------
void FlyRocketPowered::fly() const
{
  std::cout << "I'm flying with a rocket!\n";
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitQuackBehavior.h

 

//---------------------------------------------------------------------------
#ifndef UnitQuackBehaviorH
#define UnitQuackBehaviorH
//---------------------------------------------------------------------------
struct QuackBehavior
{
  virtual void quack() const = 0;
  virtual ~QuackBehavior() {} //All ABC's must have a virtual destructor
};
//---------------------------------------------------------------------------
struct Quack : public QuackBehavior
{
  void quack() const;
};
//---------------------------------------------------------------------------
struct MuteQuack : public QuackBehavior
{
  void quack() const;
};
//---------------------------------------------------------------------------
struct Squeak : public QuackBehavior
{
  void quack() const;
};
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitQuackBehavior.cpp

 

//---------------------------------------------------------------------------
#include <iostream>
#include "UnitQuackBehavior.h"
//---------------------------------------------------------------------------
void Quack::quack() const
{
  std::cout << "Quack\n";
}
//---------------------------------------------------------------------------
void MuteQuack::quack() const
{
  std::cout << "<< silence >>\n";
}
//---------------------------------------------------------------------------
void Squeak::quack() const
{
  std::cout << "Squeak\n";
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitMain.cpp

 

//---------------------------------------------------------------------------
#include <iostream>
#include <boost/shared_ptr.hpp>
#include "UnitDuck.h"
#include "UnitFlyBehavior.h"
//---------------------------------------------------------------------------
int main()
{
  {
    boost::shared_ptr<Duck> mallard(new MallardDuck);
    mallard->display();
    mallard->performQuack();
    mallard->performFly();
  }
  {
    boost::shared_ptr<Duck> rubberDuck(new RubberDuck);
    rubberDuck->display();
    rubberDuck->performQuack();
    rubberDuck->performFly();
  }
  {
    boost::shared_ptr<Duck> modelDuck(new ModelDuck);
    modelDuck->display();
    modelDuck->performQuack();
    modelDuck->performFly();
    std::cout << "Let the modelduck fly rocket powered!\n";
    boost::shared_ptr<FlyBehavior> rocketPowered(new FlyRocketPowered);
    modelDuck->setFlyBehavior(rocketPowered);
    modelDuck->performFly();
  }
}
//---------------------------------------------------------------------------

 

 

 

 

 

References

 

  1. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns. 1995. ISBN: 0201633612.
  2. Eric Freeman, Elisabeth Freeman. Head First Design Patterns. 2004. ISBN: 978-0-596-00712-6.

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict