Design pattern
A design pattern uses various co-operating objects (classes, relationships etc) to provide solutions for common software requirements.
- Observer Pattern: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
- 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.
- Decorator Pattern: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality.
#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