Fabrique abstraite (Motif de conception)

Fabrique abstraite (Motif de conception)

Fabrique abstraite (patron de conception)

La fabrique abstraite est un patron de conception (design pattern) créationnel utilisé en génie logiciel.

Une fabrique abstraite encapsule un groupe de fabriques ayant une thématique commune. Le code client crée une implémentation concrète de la fabrique abstraite, puis utilise les interfaces génériques pour créer des objets concrets de la thématique. Le client ne se préoccupe pas de savoir laquelle de ces fabriques a donné un objet concret, car il n'utilise que les interfaces génériques des objets produits. Ce patron de conception sépare les détails d'implémentation d'un ensemble d'objets de leur usage générique.

Un exemple de fabrique abstraite : la classe documentCreator fournit une interface permettant de créer différents produits (e.g. createLetter() et createResume()). Le système a, à sa disposition, des versions concrètes dérivées de la classe documentCreator, comme par exemple fancyDocumentCreator et modernDocumentCreator, qui possèdent chacune leur propre implémentation de createLetter() et createResume() pouvant créer des objets tels que fancyLetter ou modernResume. Chacun de ces produits dérive d'une classe abstraite simple comme Letter ou Resume, connues du client. Le code client obtient une instance de documentCreator qui correspond à sa demande, puis appelle ses méthodes de fabrication. Tous les objets sont créés par une implémentation de la classe commune documentCreator et ont donc la même thématique (ici, ils seront tous fancy ou modern). Le client a seulement besoin de savoir manipuler les classes abstraites Letter ou Resume, et non chaque version particulière obtenue de la fabrique concrète.

Une fabrique est un endroit du code où sont construits des objets. Le but de ce patron de conception est d'isoler la création des objets de leur utilisation. On peut ainsi ajouter de nouveaux objets dérivés sans modifier le code qui utilise l'objet de base.

Avec ce patron de conception, on peut interchanger des classes concrètes sans changer le code qui les utilise, même à l'exécution. Toutefois, ce patron de conception exige un travail supplémentaire lors du développement initial, et apporte une certaine complexité qui n'est pas forcément souhaitable.

Sommaire

Utilisation

La fabrique détermine le type de l'objet concret qu'il faut créer, et c'est ici que l'objet est effectivement créé (dans le cas du C++, c'est l'instruction new). Cependant, la fabrique retourne un pointeur abstrait sur l'objet concret créé.

Le code client est ainsi isolé de la création de l'objet en l'obligeant à demander à une fabrique de créer l'objet du type abstrait désiré et de lui en retourner le pointeur.

Comme la fabrique retourne uniquement un pointeur abstrait, le code client qui sollicite la fabrique ne connaît pas et n'a pas besoin de connaître le type concret précis de l'objet qui vient d'être créé. Cela signifie en particulier que :

  • Le code client n'a aucune connaissance du type concret, et ne nécessite donc aucun fichier header ou déclaration de classe requis par le type concret. Le code client n'interagit qu'avec la classe abstraite. Les objets concrets sont en effet créés par la fabrique, et le code client ne les manipule qu'avec leur interface abstraite.
  • L'ajout de nouveaux types concrets dans le code client se fait en spécifiant l'utilisation d'une fabrique différente, modification qui concerne typiquement une seule ligne de code (une nouvelle fabrique crée des objets de types concrets différents, mais renvoie un pointeur du même type abstrait, évitant ainsi de modifier le code client). C'est beaucoup plus simple que de modifier chaque création de l'objet dans le code client. Si toutes les fabriques sont stockées de manière globale dans un singleton et que tout le code client utilise ce singleton pour accéder aux fabriques pour la création d'objets, alors modifier les fabriques revient simplement à modifier l'objet singleton.

Structure

Fabrique abstraite UML.svg

Exemples

C++

 /* exemple d'une fabrique abstraite d'eléments d'IHM en C++ */
 
struct Button {
  virtual void paint() = 0;
};
 
struct WinButton : public Button {
  void paint (){
    std::cout << " I'm a window button \n";
  }
};
 
struct OSXButton : public Button {
  void paint (){
    std::cout << " I'm a OSX button \n";
  }
};
 
struct GUIFactory {
  virtual Button* createButton () = 0;
};
 
struct WinGUIFactory : public GUIFactory {
  Button* createButton (){
    return new WinButton();
  }
};
 
struct OSXGUIFactory : public GUIFactory {
  Button* createButton (){
    return new OSXButton();
  }
};
 
struct Application {
    Application(GUIFactory* factory){
        Button * button = factory->createButton();
        button->paint();
    }
};
 
/* application : */
 
int main()
{
  GUIFactory* factory1 = new WinGUIFactory();
  GUIFactory* factory2 = new OSXGUIFactory();
 
  Application* winApp  = new Application (factory1); 
  Application* osxApp  = new Application (factory2);
 
  delete factory1, factory2;
 
  return 0;
}

C#

/*
 * GUIFactory example
 */
 
 abstract class GUIFactory {
     public static GUIFactory getFactory() {
         int sys = readFromConfigFile("OS_TYPE");
         if (sys==0) {
             return(new WinFactory());
         } else {
             return(new OSXFactory());
         }
    }
    public abstract Button createButton();
 }
 
 class WinFactory:GUIFactory {
     public override Button createButton() {
         return(new WinButton());
     }
 }
 
 class OSXFactory:GUIFactory {
     public override Button createButton() {
         return(new OSXButton());
     }
 }
 
 abstract class Button  {
     public string caption;
     public abstract void paint();
 }
 
 class WinButton:Button {
     public override void paint() {
        Console.WriteLine("I'm a WinButton: "+caption);
     }
 }
 
 class OSXButton:Button {
     public override void paint() {
        Console.WriteLine("I'm a OSXButton: "+caption);
     }
 }
 
 class Application {
     static void Main(string[] args) {
         GUIFactory aFactory = GUIFactory.getFactory();
         Button aButton = aFactory.createButton();
         aButton.caption = "Play";
         aButton.paint();
     }
     //output is
     //I'm a WinButton: Play
     //or
     //I'm a OSXButton: Play
 }

VB.Net

'
' * GUIFactory example
' 
MustInherit Class GUIFactory
    Public Shared Function getFactory() As GUIFactory
        Dim sys As Integer = readFromConfigFile("OS_TYPE")
        If sys = 0 Then
            Return (New WinFactory())
        Else
            Return (New OSXFactory())
        End If
    End Function
    Public MustOverride Function createButton() As Button
End Class
Class WinFactory
    Inherits GUIFactory
    Public Overloads Overrides Function createButton() As Button
        Return (New WinButton())
    End Function
End Class
Class OSXFactory
    Inherits GUIFactory
    Public Overloads Overrides Function createButton() As Button
        Return (New OSXButton())
    End Function
End Class
MustInherit Class Button
    Public caption As String
    Public MustOverride Sub paint()
End Class
Class WinButton
    Inherits Button
    Public Overloads Overrides Sub paint()
        Console.WriteLine("I'm a WinButton: " & caption)
    End Sub
End Class
Class OSXButton
    Inherits Button
    Public Overloads Overrides Sub paint()
        Console.WriteLine("I'm a OSXButton: " & caption)
    End Sub
End Class
Class Application
    Private Shared Sub Main(ByVal args As String())
        Dim aFactory As GUIFactory = GUIFactory.getFactory()
        Dim aButton As Button = aFactory.createButton()
        aButton.caption = "Play"
        aButton.paint()
    End Sub
    'output is
    'I'm a WinButton: Play
    'or
    'I'm a OSXButton: Play
End Class

Java

 /*
 * GUIFactory example
 */
 
 public abstract class GUIFactory {
    public static GUIFactory getFactory() {
         int sys = readFromConfigFile("OS_TYPE");
         if (sys == 0) {
             return(new WinFactory());
         } else {
             return(new OSXFactory());
         }
    }
    public abstract Button createButton();
 }
 
 class WinFactory extends GUIFactory {
     public Button createButton() {
         return(new WinButton());
     }
 }
 
 class OSXFactory extends GUIFactory {
     public Button createButton() {
         return(new OSXButton());
     }
 }
 
 public abstract class Button  {
     private String caption;
     public abstract void paint();
 
     public String getCaption(){
         return caption;
     }
     public void setCaption(String caption){
         this.caption = caption;
     }
 }
 
 class WinButton extends Button {
     public void paint() {
        System.out.println("I'm a WinButton: "+ getCaption());
     }
 }
 
 class OSXButton extends Button {
     public void paint() {
        System.out.println("I'm a OSXButton: "+ getCaption());
     }
 }
 
 public class Application {
     public static void main(String[] args) {
         GUIFactory aFactory = GUIFactory.getFactory();
         Button aButton = aFactory.createButton();
         aButton.setCaption("Play");
         aButton.paint();
     }
     //output is
     //I'm a WinButton: Play
     //or
     //I'm a OSXButton: Play
 }

Perl

 # GUIFactory example on Perl
 
 package GUIFactory;
 
 sub getFactory($$) {
         shift; # skip class
         my $toolkit = shift;
         if ($toolkit eq 'GTK') {
             return(GtkFactory->new);
         } else {
             return(TkFactory->new);
         }
 }
 
 package GtkFactory;
 use base 'GUIFactory';
 
 sub new {
     bless({}, shift);
 }
 
 sub createButton {
         return(GtkButton->new);
 }
 
 package TkFactory;
 use base 'GUIFactory';
 
 sub new {
         bless({}, shift);
 }
 
 sub createButton() {
         return(TkButton->new);
 }
 
 package Button;
 
 sub new {
         $class = shift;
         my $self = {};
         $self{caption} = '';
         bless($self, $class);
         return $self;
 }
 
 package GtkButton;
 use base 'Button';
 
 sub paint() {
        print "I'm a GtkButton\n";
 }
 
 package TkButton;
 use base 'Button';
 
 sub paint() {
        print "I'm a TkButton\n";
 }
 
 package main;
 
 my $aFactory = GUIFactory->getFactory;
 my $aButton = $aFactory->createButton;
 $aButton->{caption} = "Play";
 $aButton->paint();

PHP

/*
 * Fabrique abstraite
 */
abstract class GUIFactory {
    public static function getFactory() {
        $sys = readFromConfigFile("OS_TYPE");
        if ($sys == 0) {
            return(new WinFactory());
        } else {
            return(new OSXFactory());
        }
    }
    public abstract function createButton();
}
 
class WinFactory extends GUIFactory {
    public function createButton() {
        return(new WinButton());
    }
}
 
class OSXFactory extends GUIFactory {
    public function createButton() {
        return(new OSXButton());
    }
}
 
abstract class Button {
    private $_caption;
    public abstract function render();
 
    public function getCaption(){
        return $this->_caption;
    }
    public function setCaption($caption){
        $this->_caption = $caption;
    }
}
 
class WinButton extends Button {
    public function render() {
        return "Je suis un WinButton: ".$this->getCaption();
    }
}
 
class OSXButton extends Button {
    public function render() {
        return "Je suis un OSXButton: ".$this->getCaption();
    }
}
 
$aFactory = GUIFactory::getFactory();
$aButton = $aFactory->createButton();
$aButton->setCaption("Démarrage");
echo $aButton->render();
 
//Le rendu est
//Je suis un WinButton: Démarrage
//ou
//Je suis un OSXButton: Démarrage

Eiffel

 --
 -- GUI Factory example
 --
 class GUI_FACTORY_FOR_CONFIG feature
    get_factory: GUI_FACTORY is
       once
          inspect read_from_config_file("OS_TYPE")
          when 0 then
             create {WIN_FACTORY} Result
          else
             create {OSX_FACTORY} Result
          end
       end
 end
 
 deferred class GUI_FACTORY feature
    create_button: BUTTON is deferred end
 end
 
 class WIN_FACTORY inherit GUI_FACTORY feature
    create_button: WIN_BUTTON is do create Result end
 end
 
 class OSX_FACTORY inherit GUI_FACTORY feature
    create_button: OSX_BUTTON is do create Result end
 end
 
 deferred class BUTTON feature
    caption: STRING
    set_caption(value: like caption) is do caption := value end
    paint is deferred end
 end
 
 class WIN_BUTTON inherit BUTTON feature
    paint is do print("I'm a WIN_BUTTON: "+caption+"%N") end
 end
 
 class OSX_BUTTON inherit BUTTON feature
    paint is do print("I'm a OSX_BUTTON: "+caption+"%N") end
 end
 
 class APPLICATION inherit GUI_FACTORY_FOR_CONFIG creation main feature
    main is local button : BUTTON do
       button := get_factory.create_button
       button.set_caption("Play")
       button.paint
    end
 end
  • Portail de l’informatique Portail de l’informatique
Ce document provient de « Fabrique abstraite (patron de conception) ».

Wikimedia Foundation. 2010.

Contenu soumis à la licence CC-BY-SA. Source : Article Fabrique abstraite (Motif de conception) de Wikipédia en français (auteurs)

Regardez d'autres dictionnaires:

  • Fabrique abstraite (motif de conception) — Fabrique abstraite (patron de conception) La fabrique abstraite est un patron de conception (design pattern) créationnel utilisé en génie logiciel. Une fabrique abstraite encapsule un groupe de fabriques ayant une thématique commune. Le code… …   Wikipédia en Français

  • Fabrique (Motif de conception) — Fabrique (patron de conception) Pour les articles homonymes, voir Fabrique. La fabrique (factory) est un patron de conception créationnel utilisé en programmation orientée objet. Comme les autres modèles créationnels, la fabrique a pour rôle l… …   Wikipédia en Français

  • Fabrique (motif de conception) — Fabrique (patron de conception) Pour les articles homonymes, voir Fabrique. La fabrique (factory) est un patron de conception créationnel utilisé en programmation orientée objet. Comme les autres modèles créationnels, la fabrique a pour rôle l… …   Wikipédia en Français

  • Motif de conception — Patron de conception Pour les articles homonymes, voir Patron. Un patron de conception (design pattern en anglais) est un concept de génie logiciel destiné à résoudre les problèmes récurrents suivant le paradigme objet. En français on utilise… …   Wikipédia en Français

  • Monteur (Motif de conception) — Monteur (patron de conception) Le monteur (builder) est un patron de conception utilisé pour la création d une variété d objets complexes à partir d un objet source. L objet source peut consister en une variété de parties contribuant… …   Wikipédia en Français

  • Monteur (motif de conception) — Monteur (patron de conception) Le monteur (builder) est un patron de conception utilisé pour la création d une variété d objets complexes à partir d un objet source. L objet source peut consister en une variété de parties contribuant… …   Wikipédia en Français

  • Patron de Méthode (Motif de conception) — Patron de méthode (patron de conception) Patron de méthode: diagramme de classes en UML La technique du patron de méthode (Template method pattern) est un patron de conception (design pattern) comportemental utilisé en génie logiciel. Un patron… …   Wikipédia en Français

  • Patron de méthode (Motif de conception) — Patron de méthode (patron de conception) Patron de méthode: diagramme de classes en UML La technique du patron de méthode (Template method pattern) est un patron de conception (design pattern) comportemental utilisé en génie logiciel. Un patron… …   Wikipédia en Français

  • Patron de méthode (motif de conception) — Patron de méthode (patron de conception) Patron de méthode: diagramme de classes en UML La technique du patron de méthode (Template method pattern) est un patron de conception (design pattern) comportemental utilisé en génie logiciel. Un patron… …   Wikipédia en Français

  • Prototype (Motif de conception) — Prototype (patron de conception) Pour les articles homonymes, voir Prototype. Le patron de conception prototype est utilisé lorsque la création d une instance est complexe ou consommatrice en temps. Plutôt que créer plusieurs instances de la… …   Wikipédia en Français

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”