Le motif iterator
Définition
Tout l’interêt de ce motif, c’est de pouvoir accéder à une suite d’objets sans connaître la façon dont ils sont organisé. C’est à dire pouvoir parcourir des objets contenus dans un autre, sans savoir comment ils sont rangé/organisé.
Principe
Pour ce motif nous allons devoir utiliser un objet intermédiaire qui permettra d’appeler les objets “cible” un par un. Cela permet de bien séparer une série d’objets de son utilisation.
L’exemple par le code
Nous allons dans cette exemple visualiser les membres des différents clubs de la ville. Chaque club utilise sa propre façon de lister ses membres. Nous allons donc devoir utiliser le motif Iterator pour simplifier la visualisation de toutes ces personnes (pour éviter de leur faire changer tout leur code).
Commencons par définir chaque club et leurs membres.
Le Mac_club utilise un objet Array pour lister ses membres, c’est simple et apparemment ça leur suffit. L’AS400_club utilise un objet Hash, sûrement dù à l’historique. Pour simplifier, nous allons utiliser un objet Club basique, et surcharger celui-ci pour le club historique (oui, la logique aurais voulu l’inverse).
class Club
attr :membres
attr_reader :name
def initialize
@name="Mac"
@membres = []
end
def each
@membres.each {|membre| yield(membre)}
end
end
class Mac_club < Club; end
class AS400_club < Club
def initialize
@name="AS400"
@membres = Hash::new
end
def each
@membres.values.each {|membre| yield(membre)}
end
end
class Membre
attr_accessor :nom, :prenom, :mail
def initialize(attr)
@nom = attr[:nom]
@prenom = attr[:prenom]
@mail = attr[:mail]
end
end
Nous avons de la chance, les deux clubs de la ville utilisent le même type d’objet pour définir leurs membres. Par contre nous avons été obligé de spécifier deux iterateur:
- le premier permet de parcourir le tableau des membres et utilise la methode
yieldpour renvoyer l’objetmembreà chaque itération. - le deuxième permet de parcourir les valeurs de la table
Hash, mais utilise le même bloc avecyieldpour renvoyer l’objetmembre.
Et voici la partie utilisé par la mairie pour visualiser les membres des clubs de la ville.
class Asso
attr :clubs
def initialize()
@clubs=[]
end
def afficher_liste_membre
@clubs.each do |club|
puts "club: #{club.name} "
club.each do |membre|
puts " #{membre.prenom} #{membre.nom} <#{membre.mail}>"
end
end
end
end
Testons tout ça.
mac_club = Mac_club.new
mac_club.membres.push(Membre.new({
:nom => "Undeuxtrois",
:prenom => "Daniel",
:mail => "du@disquesize.com"}))
mac_club.membres.push(Membre.new({
:nom => "Tiger",
:prenom => "Victor",
:mail => "tiger@jeportebienmonnom.com"}))
mac_club.membres.push(Membre.new({
:nom => "Poirbell",
:prenom => "Helene",
:mail => "ln@glace.fr"}))
mac_club.membres.push(Membre.new({
:nom => "Iloton",
:prenom => "Frederic",
:mail => "file@nofound.org"}))
as400_club = AS400_club.new
membre = Membre.new({
:nom => "Sor",
:prenom => "Laurent",
:mail => "ls@rubynux.org"})
as400_club.membres.store(membre.nom,membre)
membre = Membre.new({
:nom => "Anri",
:prenom => "Henri",
:mail => "ha@blaguedusoir.fr"})
as400_club.membres.store(membre.nom,membre)
membre = Membre.new({
:nom => "Omplete",
:prenom => "Cristian",
:mail => "complete@presquefini.org"})
as400_club.membres.store(membre.nom,membre)
asso = Asso.new
asso.clubs.push(as400_club)
asso.clubs.push(mac_club)
asso.afficher_liste_membre
# club: AS400
# Laurent Sor <ls@rubynux.org>
# Henri Anri <ha@blaguedusoir.fr>
# Cristian Omplete <complete@presquefini.org>
# club: Mac
# Daniel Undeuxtrois <du@disquesize.com>
# Victor Tiger <tiger@jeportebienmonnom.com>
# Helene Poirbell <ln@glace.fr>
# Frederic Iloton <file@nofound.org>
Ruby offre des possibilité pour simplifier la réalisation de ce motif: voir l’exemple sur rubygarden. Cependant (même si ça me gène un peut de critiquer un auteur de rubygarden :( ) au delà de l’inspect, nos ne pouvons pas réaliser les même action sur chacun des objets récupéré par simple each. Mais c’est vrai que dans beaucoup de cas de figure, ça suffiras amplement ;-)
L’exemple à été modifié. L’utilisation de yield permet de simplifier grandement l’ancien exemple.


