Le motif strategy
Définition
Le motif strategie fait partie de la catégorie des motifs Comportementaux. Il est utilisé pour séparer un ou plusieurs comportements, logique, algorithme d’un objet.
Principe
Le principe de réalisation de ce motif est simplement de créer séparément les algorithmes d’un objet. L’objet lui par contre contient une référence sur ces algorithmes pour pouvoir les appeler au moment opportun.
L’exemple par le code
Les objets de comportement: Jouer de la musique !
Bien, nous allons faire du recrutement pour la rubyFanfare (non pas de jeu de mots avec RubyFrance ;-) ) ! Pour ça nous allons avoir besoin de musiciens sachant jouer d’un instrument. Nous allons donc écrire un Module définissant l’action de jouer de la musique. Nous avons pour ça besoin d’une méthode représentant l’action de jouer de la musique, et d’un style de musique qui sera défini par les objets “implémentant” ce module.
3 objets suffiront pour notre exemple, un Classique, un Jazz et un Rock. Chacun représente un style de musique qui se “joue”. Nous allons donc les faire utiliser le module JouerDeLaMusique. Chacun d’entre eux doit redéfinir la méthode jouer puisque le module ne joue rien.
module JouerDeLaMusique
def jouer
puts "Je ne joue rien moi ! "
end
end
class Classique
include JouerDeLaMusique
def jouer
puts "Je joue un air de Mozart"
end
end
class Jazz
include JouerDeLaMusique
def jouer
puts "Je joue un air de Miles Davis"
end
end
class Rock
include JouerDeLaMusique
def jouer
puts "Je joue un air des Rolling Stones"
end
end
L’objet principal: le Musicien
Bon maintenant que nous savons comment nous allons jouer, voyons qui vas jouer pour cette audition !
Pour cela nous avons besoin de musiciens, nous allons créer un module Musicien qui nous permettra de poser les bases communes à tout musicien. Commençons par la méthode manger, car un musicien doit manger (enfin on pourrait l’hériter d’un objet humain, voir … bon bref ce n’est pas l’objet d’aujourd’hui) . Bien sûr en plus de manger, le musicien va jouer ! On défini donc une méthode jouer.
Un attribut du musicien sera l’implémentation du style de musique qu’il va jouer, autrement dit un objet de type JouerDeLaMusique.
Ensuite nous créons simplement 2 types de musicien, un pianiste et un batteur. Ils ont chacun des spécificités même si pour notre exemple il n’y a que l’affichage qui change.
require "JouerDeLaMusique.rb"
module Musicien
attr_accessor :jouerUnMorceau
def initialize(style)
@jouerUnMorceau = style
end
def manger
puts "tous les musiciens mangent ! "
end
def jouer
@jouerUnMorceau.jouer
end
end
class JoueurDePiano
include Musicien
def afficher
puts "Je suis un pianiste"
end
end
class JoueurDeBatterie
include Musicien
def afficher
puts "Je suis un batteur"
end
end
évidemment nous pourrions très bien nous contenter d’un objet auquel on passe des paramètres pour l’affichage, le style de jeu… Mais ça ne permet pas d’écrire un code souple, donc cela nous empêche d’évoluer simplement.
L’objet qui va faire passer des auditions
Il est temps maintenant de faire passer les auditions !
Voici donc le code de qui va permettre d’auditionner deux personnes, un pianiste et un batteur (oui ça fait léger pour une fanfare… ).
Nous créons d’abord un pianiste en passant en paramètre sont style de jeu, dans notre cas Classique puis nous testons sont affichage, s’il mange puis une fois le ventre plein nous testons ce qu’il joue. Ah du mozart, c’est pas mal :-).
Ensuite un batteur se présente, il joue du Rock. Bien pareil qu’avec le pianiste, on le regarde, il mange, puis il joue: hmm les Stones, c’est toujours sympa aussi. Ah il nous dit qu’il connaît aussi d’autre style, il joue dans un groupe de Jazz, voyons ou plutot écoutons ça … tiens Miles c’est intêressant.
require "Musicien" pianiste = JoueurDePiano.new Classique.new pianiste.afficher pianiste.manger pianiste.jouer batteur = JoueurDeBatterie.new Rock.new batteur.afficher batteur.manger batteur.jouer batteur.jouerUnMorceau = Jazz.new batteur.jouer
Nous voyons ici qu’il est faicle de changer le comportement d’un objet au cours de l’execution. C’est un des interêts de ce motif. La séparation des actions peut permettre plus de souplesse pendant l’éxécution mais surtout plus de facilité pour faire évoluer le code sans tout changer.
Note: Certain aspect de prise en charge d’erreur sont volontairement absent, c’est pour rendre le code plus lisible et plus simple à comprendre.


