Go back to Richel Bilderbeek's homepage.

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

 

 

 

 

 

(C++) Example from 'Head First Design Patterns'

 

Example from 'Head First Design Patterns' [1] is an example of a Strategy Design Pattern (converted from Java to C++).

 

 

Both the FlyBehavior and QuackBehavior are Strategies.

 

 

 

 

 

Technical facts

 

Application type(s)

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: CppStrategyDesignPatternExampleHeadFirst.pro

 

TEMPLATE = app
CONFIG += console
CONFIG -= qt
QMAKE_CXXFLAGS += -std=c++11 -Wall -Wextra -Weffc++
SOURCES += \
    main.cpp \
    duck.cpp \
    flybehavior.cpp \
    quackbehavior.cpp
HEADERS += \
    duck.h \
    flybehavior.h \
    quackbehavior.h
OTHER_FILES += \
    Licence.txt

 

 

 

 

 

duck.h

 

#ifndef DUCK_H
#define DUCK_H

#include <boost/shared_ptr.hpp>
struct QuackBehavior;
struct FlyBehavior;

struct Duck
{
  Duck();
  virtual void Display() const = 0;
  void PerformFly() const;
  void PerformQuack() const;
  void Swim() const;
  void SetFlyBehavior(boost::shared_ptr<const FlyBehavior> fb);
  void SetQuackBehavior(boost::shared_ptr<const QuackBehavior> qb);

  protected:
  virtual ~Duck() {} //All ABC's must have a virtual destructor
  boost::shared_ptr<const FlyBehavior> m_fly_behavior;
  boost::shared_ptr<const QuackBehavior> m_quack_behavior;
};

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 // DUCK_H

 

 

 

 

 

duck.cpp

 

#include "duck.h"

#include <cassert>
#include <iostream>
#include "flybehavior.h"
#include "quackbehavior.h"

Duck::Duck()
  : m_fly_behavior(boost::shared_ptr<FlyBehavior>()),
    m_quack_behavior(boost::shared_ptr<QuackBehavior>())
{

}

void Duck::PerformFly() const
{
  assert(m_fly_behavior);
  m_fly_behavior->Fly();
}

void Duck::PerformQuack() const
{
  assert(m_quack_behavior);
  m_quack_behavior->Quack();
}

void Duck::Swim() const
{
  std::cout << "All ducks float, even decoys!\n";
}

void Duck::SetFlyBehavior(boost::shared_ptr<const FlyBehavior> fb)
{
  m_fly_behavior = fb;
}

void Duck::SetQuackBehavior(boost::shared_ptr<const QuackBehavior> qb)
{
  m_quack_behavior = qb;
}

MallardDuck::MallardDuck()
{
  m_fly_behavior.reset(new FlyWithWings);
  m_quack_behavior.reset(new NormalQuack);
}

void MallardDuck::Display() const
{
  std::cout << "I'm a real mallard duck\n";
}

RubberDuck::RubberDuck()
{
  m_fly_behavior.reset(new FlyNoWay);
  m_quack_behavior.reset(new Squeak);
}

void RubberDuck::Display() const
{
  std::cout << "I'm a rubber duck\n";
}

ModelDuck::ModelDuck()
{
  m_fly_behavior.reset(new FlyNoWay);
  m_quack_behavior.reset(new MuteQuack);
}

void ModelDuck::Display() const
{
  std::cout << "I'm a model duck\n";
}

 

 

 

 

 

flybehavior.h

 

#ifndef FLYBEHAVIOR_H
#define FLYBEHAVIOR_H

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 // FLYBEHAVIOR_H

 

 

 

 

 

flybehavior.cpp

 

#include "flybehavior.h"

#include <iostream>

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";
}

 

 

 

 

 

main.cpp

 

#include <iostream>
#include <boost/shared_ptr.hpp>
#include "duck.h"
#include "flybehavior.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();
  }

}

 

 

 

 

 

quackbehavior.h

 

#ifndef QUACKBEHAVIOR_H
#define QUACKBEHAVIOR_H

struct QuackBehavior
{
  virtual void Quack() const = 0;
  virtual ~QuackBehavior() {} //All ABC's must have a virtual destructor
};

struct NormalQuack : public QuackBehavior
{
  void Quack() const;
};

struct MuteQuack : public QuackBehavior
{
  void Quack() const;
};

struct Squeak : public QuackBehavior
{
  void Quack() const;
};

#endif // QUACKBEHAVIOR_H

 

 

 

 

 

quackbehavior.cpp

 

#include "quackbehavior.h"

#include <iostream>
#include "quackbehavior.h"

void NormalQuack::Quack() const
{
  std::cout << "Quack\n";
}

void MuteQuack::Quack() const
{
  std::cout << "<< silence >>\n";
}

void Squeak::Quack() const
{
  std::cout << "Squeak\n";
}

 

 

 

 

 

References

 

  1. 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