VIII. La stratégie▲
Stratégie : pattern permettant de changer d'algorithme utilisé de façon dynamique.
VIII-1. Pourquoi adopter la stratégie▲
Imaginez : vous être en train de coder une IA. Celle-ci doit effectuer différentes actions selon la situation dans laquelle elle se trouve. Comment coder ceci ? On pourrait le faire à coup de if/else mais cela serait vite une horreur. La solution la plus avantageuse est alors de passer par le pattern stratégie qui va encapsuler chaque version de l'algorithme dans une classe. Ensuite il suffira de moduler les classes appelées par le client pour changer l'algorithme utilisé de manière transparente. Avec cette petite analyse, on en déduit que le diagramme UML de ce pattern est le suivant :

VIII-2. Première implémentation▲
En reprenant l'idée d'une IA abordée dans l'introduction, un 1er exemple de ce pattern peut être
#ifndef STRATEGIE_H
#define STRATEGIE_H
class Strategie;
class IA
{
int m_puissance;
Strategie* m_strategie;
void SetStrategie(Strategie* strategie);
public:
IA();
~IA();
void ChangePuissance(int i);
void Jouer();
};
class Strategie
{
public:
void Jouer();
virtual ~Strategie() = 0;
protected:
virtual void Analyser() =0;
virtual void Appliquer() =0 ;
};
class Offensive: public Strategie
{
void Analyser();
void Appliquer();
};
class Defensive: public Strategie
{
void Analyser();
void Appliquer();
};
#endifEt dans le fichier stratégie.cpp
#include <iostream>
#include "strategie.h"
using namespace std;
IA::IA():m_strategie(new Offensive)
{
m_puissance=100;
}
void IA::Jouer()
{
if(m_puissance < 50)
SetStrategie(new Defensive);
m_strategie->Jouer();
}
void IA::SetStrategie(Strategie* strategie)
{
if(strategie != 0)
{
delete m_strategie;
m_strategie= strategie;
}
}
void IA::ChangePuissance(int i)
{
m_puissance+=i;
}
IA::~IA()
{
delete m_strategie;
}
void Strategie::Jouer()
{
Analyser();
Appliquer();
cout<<"======"<<endl;
}
Strategie::~Strategie()
{
}
void Offensive::Analyser()
{
cout<<"Envoyer des véhicules de reconnaisance"<<endl;
}
void Offensive::Appliquer()
{
cout<<"Envoyer troupes où il y'a des ennemies"<<endl;
}
void Defensive::Analyser()
{
cout<<"Se baser sur le radar"<<endl;
}
void Defensive::Appliquer()
{
cout<<"Construire defense ou il ya des ennemies"<<endl;
}
int main(void)
{
IA ia1;
for(int i=0;i<10;i++)
{
ia1.ChangePuissance(-10);
ia1.Jouer();
}
return 0;
}On voit donc ici qu'en fonction de la puissance dont elle dispose l'IA va adopter une stratégie différente sans que cela soit visible pour l'utilisateur. Sinon, il n'y a rien de difficile dans le code.
VIII-3. Remarques sur la stratégie▲
VIII-3-a. Parallèle avec les politiques▲
Ceux qui ont déjà lu l'excellent article d'Alp Mestan sur les politiques ont sans doute fait le rapport avec le pattern présenté ici. En effet, les classes de politiques sont la représentation du pattern stratégie via les templates. Sauf que celle-ci utilise le polymorphisme statique au lieu d'utiliser le polymorphisme dynamique. Je vous propose donc de vous référer à son article pour un exemple d'utilisation.


