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.

  • Pointer Chain


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

Pointer Chain 전체코드

#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;
}
⚠️ **GitHub.com Fallback** ⚠️