VIII. La stratégie▲
Stratégie : pattern permettant de changer d'algorithme utilisé de façon dynamique.
VIII-A. 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-B. 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();
}
;
#endif
Et 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 ennemis"
<<
endl;
}
void
Defensive::
Analyser()
{
cout<<
"Se baser sur le radar"
<<
endl;
}
void
Defensive::
Appliquer()
{
cout<<
"Construire defense ou il y a des ennemis"
<<
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-C. Remarques sur la stratégie▲
VIII-C-1. 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.