Go back to Richel Bilderbeek's homepage.
Go back to Richel Bilderbeek's C++ page.
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:
- UnitDuck: a Duck ABC and its derived classes
- UnitFlyBehavior: a fly behavior ABC and its derived classes
- UnitQuackBehavior: a quack behavior ABC and its derived classes
- UnitMain: holds the main function
Both the FlyBehavior and QuackBehavior are Strategies.
UnitDuck.h
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();
}
}
//---------------------------------------------------------------------------
|
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns. 1995. ISBN: 0201633612.
- 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.
