Les states que nous avons vu précédemment sont utile pour enregistrer, annuler et restaurer des états,
propres à l'application ou aux entités mais ils ne permettent pas définir le comportement des entités entre elles lors
d'une action.
C'est pour cette raison que le framework possède deux classes bien précise pour définir le comportement en fonction
du type des entités lors d'une action.
Ces deux classes s'appelles odfaeg::core::Variant et odfaeg::core::Visitor.
La classe odfaeg::core::Variant va juste définir la liste des types d'entités pouvant être contenue dans un std::vector
par exemple.
Tandit que l'interface odfaeg::core::Visitor va définir la classe qui va définir les comportements en fonction du type des
entités participant à l'action à l'aide de foncteurs.
Prenons par exemple une classe Chien et une classe Chat qui sont deux entités de type différent.


    class Chien {
    };
    class Chat {
    };
    

On va définir un classe attaquer héritant de odfaeg::core::visitor qui va contenir quatre foncteurs différent,
vu qu'il y a 4 comportements différent possibles :
Un chat attque un chat, un chat attaque un chien, un chien attaque un chat et un chien attaque un chient.
Il va donc y avoir 4 foncteurs différents :


    class Attaquer : public odfaeg::core::Visitor<> {
        void operator()(const chat&, const chat&) const
        { std::cout <<  "griffe - griffe" << std::endl;}
        void operator()(const chat&, const chien&) const
        { std::cout <<  "griffe - mord  " << std::endl;}
        void operator()(const chien&, const chat&) const
        { std::cout <<  "mord - griffe" << std::endl;}
        void operator()(const chien&, const chien&) const
        { std::cout << "mord - mord  " << std::endl;}
    };
    

L'interface odfaeg::core::Visitor prend un paramètre template, c'est le type de retour renvoyé par les foncteurs, ici,
ils ne renvoient rien donc on laisse vide.
Ici il y a deux paramères aux foncteurs, il y aura donc, deux variants.
Les visiteurs définissant des comportements pour plusieurs variants sont appelé des n-ary visitors.
Il faudra donc appler la méthode odfaeg::core::apply_nary_visitor sur nos variants.


    int main() {
        Chien chien;
        Chat chat;
        std::vector,odfaeg::core::Variant>> list;
        list.push_back(std::make_pair(chat, chat));
        list.push_back(std::make_pair(chat, chien));
        list.push_back(std::make_pair(chien, chat));
        list.push_back(std::make_pair(chien, chien));
        Attaquer attaquer;
        for (unsigned int i = 0; i < list.size(); i++) {
          odfaeg::apply_nary_visitor(attaquer, list[i].first, list[i].second);
        }
    }
    

Si vos foncteurs ne prennent qu'un seul variant en paramètre, alors, vous devez appeler la méthode odfaeg::core::apply_visitor!
Voilà, sinon sachez qu'il existe une autre manière de faire :


      struct chat;
      struct chien;
      struct animal
        : odfaeg::accept_visitor
      { };
       
      struct chat
              : odfaeg::acceptable
      { };
       
      struct chien
              : odfaeg::acceptable
      { };
      struct attaquer
              : odfaeg::dispatchable
      {
              void operator()(const chat&, const chat&) const
              { std::cout <<  "griffe - griffe" << std::endl;}
              void operator()(const chat&, const chien&) const
              { std::cout <<  "griffe - mord  " << std::endl;}
              void operator()(const chien&, const chat&) const
              { std::cout <<  "mord - griffe" << std::endl;}
              void operator()(const chien&, const chien&) const
              { std::cout << "mord - mord  " << std::endl;}
      };
      int main() {
        chat c1;
        chien c2; 
        animal& a1 =c1;
        animal& a2 =c2; 
        attaquer().apply(a1,a1);
        attaquer().apply(a1,a2);
        attaquer().apply(a2,a1);
        attaquer().apply(a2,a2);
      }
    

La seule différence ici est que les objets chien et chat ont quelque chose en commun, vu qu'ils héritent de la classe
animal.
Cependant il faut hériter de plusieurs interfaces, la première (accept_visitor) prend en paramètre template la classe de base
ainsi que les sous classes de la famille.
L'interface acceptable prend en paramètre la classe de base et la classe dérivée.
Et enfin l'interface dispatchable prend en paramètre la classe définissant l'action et la classe de base.
l'interface dispatchable peut prendre plusieurs familles en paramètre template, donc, dans ce cas-ci on pourrait avoir d'autres
familles d'objets que des animaux.
Voila ce qui clôture ce chapitre!
Utiliser les classes utilitaires de odfaeg ainsi que les states sont de bon moyen pour éviter de devoir faire trop d'héritage!