Chain_of_Responsibility_Pattern_2 - 8BitsCoding/RobotMentor GitHub Wiki
-
Chain of Responsibility : A chain of components who all get a chance to process a command or a query, optionally having default processing implementation and an ability to terminate the processing chain.
struct Creature
{
string name;
int attack, defense;
Creature(const string & name, int attack, int defense) : name(name), attack(attack), defense(defense) {}
friend ostream &operator<<(ostream& os, const Creature& creature) {
os << "name: " << creature.name << " attack: " << creature.attack << " defense " << creature.defense;
return os;
}
};
class CreatureModifier
{
CreatureModifier* next{nullptr};
protected:
Creature& creature;
public:
CreatureModifier(Creature& creature) : creature(creature) {}
void add(CreatureModifer* cm)
{
if(next) next->add(cm);
else next = cm;
}
virtual void handle()
{
if(next) next->hangle();
}
};
class DoubleAttackModifier : public CreatureModifier
{
public:
DoubleAttackModifier(Creature& creature) : CreatureModifier(creature) {}
void handle() override {
creature.attack *= 2;
CreatureModifier::handle();
}
};
class IncreaseDefenseModifier : public CreatureModifier
{
public:
IncreaseDefenseModifier(Creature& creature) : CreatureModifier(creature) {}
void handle() override {
if(creature.attack <=2)
creatrue.defense++;
CreatureModifier::handle();
}
};
class NoBonusesModifier : public CreatureModifier
{
public:
NoBonusesModifier(Creature& creature) : CreatureModifier(creature) {}
void handle() override {
CreatureModifier::handle();
}
};
int main()
{
Creature gobliin{"Goblin", 1, 1};
CreatureModifier root{gobliin};
DoubleAttackModifier r1{gobliin};
DoubleAttackModifier r1_2{gobliin};
IncreaseDefenseModifier r2{gobliin};
root.add(&r1);
root.add(&r1_2);
root.add(&r2);
root.handle();
cout << goblin << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
struct Creature
{
string name;
int attack, defense;
Creature(const string& name, const int attack, const int defense)
: name(name),
attack(attack),
defense(defense)
{
}
friend ostream& operator<<(ostream& os, const Creature& obj)
{
return os
<< "name: " << obj.name
<< " attack: " << obj.attack
<< " defense: " << obj.defense;
}
};
class CreatureModifier
{
CreatureModifier* next{ nullptr }; // unique_ptr
protected:
Creature& creature; // pointer or shared_ptr
public:
explicit CreatureModifier(Creature& creature)
: creature(creature)
{
}
virtual ~CreatureModifier() = default;
void add(CreatureModifier* cm)
{
if (next) next->add(cm);
else next = cm;
}
// two approaches:
// 1. Always call base handle(). There could be additional logic here.
// 2. Only call base handle() when you cannot handle things yourself.
virtual void handle()
{
if (next) next->handle();
}
};
// 1. Double the creature's attack
// 2. Increase defense by 1 unless power > 2
// 3. No bonuses can be applied to this creature
class NoBonusesModifier : public CreatureModifier
{
public:
explicit NoBonusesModifier(Creature& creature)
: CreatureModifier(creature)
{
}
void handle() override
{
// nothing
}
};
class DoubleAttackModifier : public CreatureModifier
{
public:
explicit DoubleAttackModifier(Creature& creature)
: CreatureModifier(creature)
{
}
void handle() override
{
creature.attack *= 2;
CreatureModifier::handle();
}
};
class IncreaseDefenseModifier : public CreatureModifier
{
public:
explicit IncreaseDefenseModifier(Creature& creature)
: CreatureModifier(creature)
{
}
void handle() override
{
if (creature.attack <= 2)
creature.defense += 1;
CreatureModifier::handle();
}
};
int main_()
{
Creature goblin{ "Goblin", 1, 1 };
CreatureModifier root{ goblin };
DoubleAttackModifier r1{ goblin };
DoubleAttackModifier r1_2{ goblin };
IncreaseDefenseModifier r2{ goblin };
//NoBonusesModifier nb{ goblin }; // effectively Command objects
//root.add(&nb);
root.add(&r1);
root.add(&r1_2);
root.add(&r2);
root.handle(); // annoying
cout << goblin << endl;
//getchar();
return 0;
}