Résumé des patrons de conception expliqués dans le livre Design Patterns in Ruby
View the Project on GitHub armandfardeau/design-patterns-in-ruby
Nous voulons qu’un objet parle à un autre mais leurs interfaces ne correspondent pas.
Nous enveloppons simplement l’adaptateur avec notre nouvelle classe d’adaptateur. Cette classe implémente une interface que l’appelant comprend, bien que tout le travail soit effectué par l’objet adapté.
Pensons à une classe qui chiffre un fichier, qui prend deux fichiers ouverts, l’un pour la lecture et l’autre pour l’écriture :
class Encrypter
def initialize(key)
@key = key
end
def encrypt(reader, writer)
key_index = 0
while not reader.eof?
clear_char = reader.getc
encrypted_char = clear_char ^ @key[key_index]
writer.putc(encrypted_char)
key_index = (key_index + 1) % @key.size
end
end
end
Que se passe-t-il si les données que nous voulons sécuriser se trouvent dans une chaîne de caractères plutôt que dans un fichier ? Nous avons besoin d’un objet qui ressemble à un fichier ouvert, c’est-à-dire qui supporte la même interface que l’objet Ruby IO
. Nous pouvons créer un StringIOAdapter
pour y parvenir :
class StringIOAdapter
def initialize(string)
@string = string
@position = 0
end
def getc
if @position >= @string.length
raise EOFError
end
ch = @string[@position]
@position += 1
return ch
end
def eof?
return @position >= @string.length
end
end
Maintenant nous pouvons utiliser une String
comme s’il s’agissait d’un fichier ouvert (il n’implémente qu’une petite partie de l’interface IO
essentiellement ce dont nous avons besoin).
encrypter = Encrypter.new('XYZZY')
reader= StringIOAdapter.new('We attack at dawn')
writer=File.open('out.txt', 'w')
encrypter.encrypt(reader, writer)