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.