Design pattern

A design pattern uses various co-operating objects (classes, relationships etc) to provide solutions for common software requirements.
#include <iostream>
#include <list>
#include <string>
using namespace std;

// Standard interfaces
class Subject;
class IObserver {
public:
  virtual void Update(const Subject* subject) = 0;
};

class Subject {
public:
  void AttachObserver(IObserver* observer) { observers_.push_back(observer); }
  void DetachObserver(IObserver* observer) { observers_.remove(observer); }

protected:
  void NotifyObservers(void) const
  {
    for (list::const_iterator it=observers_.begin(); it!=observers_.end(); it++)
      (*it)->Update(this);
  }

private:
  list observers_;
};

class TeamStrategy {
public:
  virtual void Play(void) const = 0;
};


// Implementation classes
struct Position {
public:
  Position(void) : x_(0), y_(0), z_(0) {}
  friend ostream& operator<<(ostream& outStream, const Position& position);

  int x_;
  int y_;
  int z_;
};
ostream& operator<<(ostream& outStream, const Position& position)
{
  outStream << position.x_ << "," << position.y_ << "," << position.z_;
  return outStream;
}

class Football : public Subject {
public:
  void SetPosition(const Position& position)
  {
    position_ = position;
    NotifyObservers();
  }
  void SetPosition(const int x, const int y, const int z)
  {
    position_.x_ = x;
    position_.y_ = y;
    position_.z_ = z;
    NotifyObservers();
  }
  Position GetPosition(void) const { return position_; }

private:
  Position position_;
};

class Referee : public IObserver {
public:
  Referee(Football* football, string name) : football_(football), name_(name) {}
  virtual void Update(const Subject* subject)
  {
    if (subject == football_)
      cout << "Referee " << name_ << " say that the ball is at " << football_->GetPosition() << endl;
    else
      cerr << "Referee being notified but unknown subject!" << endl;
  }

private:
  Football* football_;
  string name_;
};

class Player : public IObserver {
public:
  Player(void) {}
  Player(Football* football, const string& name) : football_(football), name_(name) {}
  virtual void Update(const Subject* subject)
  {
    if (subject == football_)
      cout << "Player " << name_ << " say that the ball is at " << football_->GetPosition() << endl;
    else
      cerr << "Player being notified but unknown subject!" << endl;
  }

  string GetName(void) const { return name_; }
  virtual void PassBall(void) { cout << "Player " << name_ << " pass the ball" << endl; }

protected:
  string name_;
private:
  Football* football_;
};


class PlayerRole : public Player {
public:
  void AssignPlayer(Player* player) { player_ = player; }
  virtual void PassBall(void) { player_->PassBall(); }

protected:
  Player* player_;
};

class GoalKeeper : public PlayerRole {
public:
  void PassBall(void) { cout << "GoalKeeper " << player_->GetName() << " pass the ball" << endl; }
  void SaveBall(void) { cout << "GoalKeeper " << player_->GetName() << " save the ball!" << endl; }
};

class Defender : public PlayerRole {
public:
  void Defend(void) { cout << "Defender " << player_->GetName() << " defend the ball!" << endl; }
};

class MidFielder : public PlayerRole {
public:
  void Dribble(void) { cout << "MidFielder " << player_->GetName() << " dribble the ball" << endl; }
};

class Forward : public PlayerRole {
public:
  void ShootGoal(void) { cout << "Forward " << player_->GetName() << " shoot the ball to goalpost!" << endl; }
};


class AttackStrategy : public TeamStrategy {
public:
  virtual void Play(void) const
  {
    cout << "Playing in attacking mode" << endl;
  }
};

class DefendStrategy : public TeamStrategy {
public:
  virtual void Play(void) const
  {
    cout << "Playing in defensive mode" << endl;
  }
};

class Team {
public:
  Team(string name) : name_(name) {}
  void SetStrategy(TeamStrategy* strategy) { strategy_ = strategy; }
  void PlayGame(void)
  {
    cout << "Team " << name_ << "\n\t";
    strategy_->Play();
  }

private:
  string name_;
  TeamStrategy* strategy_;
};

int main(int argc, char *argv[])
{
  Football football;

  Referee referee1(&football, "1");
  Referee referee2(&football, "2");
  Player owen(&football, "Owen");
  Player beckham(&football, "Beckham");

  football.AttachObserver(&referee1);
  football.AttachObserver(&referee2);
  football.AttachObserver(&owen);
  football.AttachObserver(&beckham);

  cout << "After attaching the observers..." << endl;
  football.SetPosition(10, 30, 20);
  cout << endl;

  football.DetachObserver(&referee1);
  football.DetachObserver(&owen);

  cout << "After detaching some observers..." << endl;
  football.SetPosition(20, 10, 30);
  cout << endl;


  AttackStrategy attack;
  DefendStrategy defend;

  Team brazil("Brazil");
  Team italy("Italy");

  brazil.SetStrategy(&attack);
  italy.SetStrategy(&defend);

  cout << "After setting the strategies... " << endl;
  brazil.PlayGame();
  italy.PlayGame();
  cout << endl;


  Player khan(&football, "Khan");

  cout << "Warm up session..." << endl;
  khan.PassBall();
  beckham.PassBall();
  owen.PassBall();
  cout << endl << "Match is starting..." << endl;

  Forward forward;
  MidFielder midfielder;
  GoalKeeper goalkeeper;

  forward.AssignPlayer(&owen);
  midfielder.AssignPlayer(&beckham);
  goalkeeper.AssignPlayer(&khan);

  goalkeeper.PassBall();
  midfielder.Dribble();
  midfielder.PassBall();
  forward.ShootGoal();

  cout << endl << "Oops, Owen got injured. Jerrard replace Owen for penalty..." << endl;
  Player jerrard(&football, "Jerrard");
  forward.AssignPlayer(&jerrard);
  forward.ShootGoal();

  cout << endl << "Oh no, counter-attack from opposite team, Beckham has to defend too." << endl;
  Defender defender;
  defender.AssignPlayer(&beckham);
  defender.Defend();

  cout << "Oh no, Beckham fail to defend..." << endl;
  goalkeeper.SaveBall();
  cout << "Excellent save, now the ball is on Khan hands" << endl;
  goalkeeper.PassBall();
  midfielder.Dribble();
  midfielder.PassBall();
  forward.ShootGoal();

  cout << "Goal!" << endl;

  return 0;
}
Index