le motif adapter

Définition

Ce motif permet de faire communiquer deux classes qui, à cause de leurs interfaces, ne devrais pas pouvoir le faire.

Principe

Tout comme on utilise un adapteur pour branché nos appareil électrique (Européen) dans des prises qui ne distribuent que 110V, le motif adapteur vas venir se mettre entre deux classes ne pouvant pas communiquer. En prenant en reproduisant la signature de l’une à partir des spécifications de l’autre.

L’exemple par le code

Nous allons utiliser deux sources de donnée dans un même projet. L’une permettras d’obtenir un objet à partir d’une base de donnée, et l’autre de récupérer un objet à partir d’un fichier.

module Database
  attr :database
  def initialize(database = "")
    @database = database
  end
  def get_object(object)
  end
end
class Mysql
  include Database
  def get_object(object)
    puts "J'effectue mon select sur #{@database} pour construire l'objet  #{object}"  
  end
end
class FileSource
  attr :file
  def initialize(file="")
    @file = file
  end
  def deserialize_object(object)
    puts "J'effectue la deserialisation de mon fichier: #{@file} pour obtenir l'objet  #{object}" 
  end
end

Nous utilisons un module pour les classe qui lirons dans les base de données. Effectivement on peut imaginer que selon la base de donnée, on utilise quelque spécificité. En fait c’est surtout pour les besoins de l’exemple.

Ensuite il nous faut écrire l’adapteur. Effectivement la classe que l’on nous a fourni ne peut pas être modifier, et elle n’utilise pas le même interface… deserialize_object à la place de get_object

class AdapterSerializer
  include Database
  def initialize(file_source)
    @source_to_adapt=file_source
  end
  def get_object(object)
    @source_to_adapt.deserialize_object(object)
  end
end

Nous adaptons la méthode get_object pour quelle appel la méthode deserialize_object.

Testons l’ensemble:

database_source = Mysql.new("mysql:toto/bidon@localhost:3336")
file_source = FileSource.new("/var/data/monfichier")
source = AdapterSerializer.new(file_source)
object = "mon objet" 
file_source.deserialize_object(object)
database_source.get_object(object)
source.get_object(object)

Et nos obtenons:

J'effectue la deserialisation de mon fichier: /var/data/monfichier pour obtenir l'objet  mon objet
J'effectue mon select sur mysql:toto/bidon@localhost:3336 pour construire l'objet  mon objet
J'effectue la deserialisation de mon fichier: /var/data/monfichier pour obtenir l'objet  mon objet

En appellant la même méthode sur nos deux objets, nous obtenons le bon résultat, malgrès leur différence. En fait nous faisons passer notre objet de deserialization pour un objet de base de donnée.