Bonjour à tous,
J’ai mis en place un strategy pattern pour l’écriture d’un analyseur de fichiers textes. L’idée est d’appliquer différentes stratégies à un même fichier en fonction des besoins : récupérer certaines infos, faire des calculs statistiques, etc.
Mon soucis réside dans une modélisation objet propre et cohérente des classes externes utilisées lors des différentes stratégies. Attention, pas d’héritage multiple (code Java ou PHP).
Pour être plus concret :
il s’agit de fichiers textes d’historiques de parties de poker
j’ai un donc une classe Partie qui contient des Mains
class Main
{
...
}
class Partie
{
Main mains[];
}
une stratégie donnée va créer un objet Partie et ses Main(s) associées
class Strategie implements IStrategie // strategy pattern
{
Partie partie;
function Analyse()
{
partie = new Partie();
...
}
}
et cette stratégie va avoir besoin d’attributs spécifiquement pour elle à associer à chaque Main, ou à la Partie
évidemment, je ne peux pas intégrer ces attributs dans les classes Main ou Partie puisqu’ils ne servent que pour une stratégie donnée (et donc pas les autres)
Ma question est donc : comment faire ? Dois-je créer des classes spécifiques à la stratégie ?
class MainPourStrategieA extends Main
{
Int x; // utile uniquement dans le cadre de la stratégie A
}
Cette solution me semble la plus évidente, mais aussi la plus lourdingue.
D’autre part j’ai un soucis de sémantique : quels noms donner à ces classes spécifiques à des stratégies données ?
Y a t’il d’autres approches (design patterns ?), d’autres façons de voir ?
Etant un programmeur old-school et très orienté procédural, je me pose beaucoup (trop) de questions sur les approches orientées objet et la façon de concevoir propre, cohérent, logique et… beau
Je suis pas sur de comprendre ton problème à 100%, mais je pense que dans l’idéal, ta classe Stratégie va recevoir des paramètres, paramètres qui serviront à instancier une partie et ses mains.
Dans ton cas, la méthode Analyse() recevrait des paramètres qui seraient passés au(x) constructeur(s) de Partie et Main. Ca te permettra de rester générique.
Mon problème est que j’ai une Partie qui contient des mains. Et dans le cadre d’une stratégie, j’ai besoin d’attributs supplémentaires dans la classe Main. J’imagine que ça serait très sale de les mettre dans la classe Main. Ce qui m’oblige donc à créer une classe spécifique pour ces attributs (MainPourStrategieA). Ca me semble pas terrible, et je me demande donc si mon modèle est cohérent…
Vu que je suis une über buse au poker, c’est pas facile de t’aider à modéliser ça
Quels sont ces attributs qui ne font normalement pas partie d’une main?
Dans le pire des cas, une main pourrait posséder une variable membre qui serait une référence vers cet attribut (référence qui pourrait être nulle dans le cas d’une main « normale »), mais c’est pas encore l’idéal je pense.
C’est surtout des attributs spécifiques à la stratégie, au niveau de chaque Main.
Par exemple, le « coeur » d’une main est composée de 5 cartes communes.
Nous aurons donc :
class Main
{
Carte cartes_communes[5];
}
On aura besoin de cet attribut dans toutes les stratégies.
Maintenant, prenons une stratégie qui a besoin de calculer et de stocker la moyenne des jetons en jeu de chaque main. Il n’y a que cette stratégie qui a besoin de calculer et stocker ce nombre. Aucune autre stratégie n’en a besoin.
Je ne peux donc pas écrire (sale !):
class Main
{
Carte cartes_communes[5];
float moyenne_jetons;
}
Je peux faire quelque chose comme :
class StrategieA implements IStrategie
{
Partie partie; // La classe Partie contient un tableau de Main
float moyennes_jetons[];
}
Ou encore :
class MainPourStrategieA extends Main
{
float moyennes_jetons;
... // autres attributs utiles uniquement pour StrategieA
}
class StrategieA implements IStrategie
{
Partie partie;
MainPourStrategieA mains[];
}
Dans tous les cas, je reste sur ma faim. J’ai le sentiment que mon modèle de départ n’est pas terrible…
Ok je comprends mieux. Dans ce cas l’idée d’une classe de base Main dérivée pour chaque stratégie me choque beaucoup moins: Si chaque stratégie a besoin de diverses variables supplémentaires pour chaque main, il n’y a pas de miracle.
class Strategie {
class Main extends package1.Main {
}
Main[] mains;
......
}[/code]
perso j’aurais plutot tendance a mettre la logique dans la classe strategie. Main n’a certainement pas vocation a contenir des statitiques.
Pour t’en convaincre, demande toi ou tu mettrais tes stats sur la main actuelle + les mains précédentes. Certainement pas dans la main !
un truc comme ca :
class Strategie {
Main[] Mains;
Stat[] stats;
......
}
ou
class Strategie {
Pair<Main, Stat>[] Mains;
......
}
ou encore
class Stat {
Main[] mainsPrecedentes;
Main mainCourante
...
}
class Strategie {
Stat[] stats;
......
}
(entre les 3, la derniere me parait la plus logique).
L’idée, c’est que la Strategie ne travaille pas vraiment sur une main mais plus sur des stats. De plus, une main, c’est un truc assez statique tres bien définie.
Tout ca est a peaufiner bien entendu