Le motif abstract factory

Définition

Ce motif permet la création d’objet par le biais d’une fabrique, qui elle même fera appel a des fabriques dites concrêtes mais sans avoir à les spécifier (c’est là une des différences avec le motif factory).

Principe

Découpler l’objet utilisateur de l’objet fabriquant rend le mode d’instanciation plus souple. On ne se soucie plus de la façon de créer un objet… Le motif fabrication utilise la composition (c’est une autre différence avec le motif factory qui lui préfère l’héritage)

L’exemple par le code

Reprenons l’exemple du motif factory, celui des parseurs.

Nous allons juste ajouter une fabrique abstraite: ParserFactoryCenter

 class ParserFactoryCenter
   @@factories = []
   def ParserFactoryClass.add_factory( p )
     @@factories.push( p )
   end
   def ParserFactoryClass.factories
     return @@factories
   end
   def ParserFactoryClass.parser_for( type )
     @@factories.each do |parser_factory|
       if parser_factory.type == type 
         return parser_factory.parser
       end
     end
     return nil
   end
 end
 ParserFactoryClass.add_factory( WikiFactory.new )
 ParserFactoryClass.add_factory( HtmlFactory.new )

Nous ajoutons à la fin nos deux fabriques.

Nous pouvons maintenant tester cela. Finalement le grand changement c’est que nous n’avons plus besoin de connaitre la fabrique que nous souhaitons utiliser, c’est l’objet ParserFactoryCenter qui nous fournira ce qu’il nous faut.

Nous sommes même capables de lui demander une liste des parseurs disponibles ! :-)

 print "Parseur disponible:"                               # -> Parseur disponible
 ParserFactoryClass.factories.each do |factory|
   print factory.type                                      # -> Wiki, HTML
 end
 wiki_parseur = ParserFactoryClass.parser_for( "Wiki" )

 print wiki_parseur                                        # -> #<WikiParser:0xb7c81f04>

 print wiki_parseur.parse("source wiki")                   # -> Je parse très bien le langage wiki
 html_parseur = ParserFactoryClass.parser_for( "HTML" )

 print html_parseur                                        # -> #<HtmlParser:0xb7c81ec8>

 print html_parseur.parse("source html")                   # -> Je parse très bien le HTML