Modèle d'usine. Quand utiliser les méthodes d'usine?


Réponses:


386

J'aime penser aux modèles de conception en termes de mes classes étant des «personnes», et les modèles sont les façons dont les gens se parlent.

Donc, pour moi, le modèle d'usine est comme une agence d'embauche. Vous avez quelqu'un qui aura besoin d'un nombre variable de travailleurs. Cette personne peut connaître les informations dont elle a besoin chez les personnes qu'elle embauche, mais c'est tout.

Ainsi, lorsqu'ils ont besoin d'un nouvel employé, ils appellent l'agence d'embauche et leur disent ce dont ils ont besoin. Maintenant, pour réellement embaucher quelqu'un, vous devez connaître beaucoup de choses - avantages sociaux, vérification de l'admissibilité, etc. Mais la personne qui embauche n'a pas besoin de savoir tout cela - l'agence d'embauche gère tout cela.

De la même manière, l'utilisation d'une usine permet au consommateur de créer de nouveaux objets sans avoir à connaître les détails de la façon dont ils ont été créés, ni quelles sont leurs dépendances - ils n'ont qu'à fournir les informations qu'ils souhaitent réellement.

public interface IThingFactory
{
    Thing GetThing(string theString);
}

public class ThingFactory : IThingFactory
{
    public Thing GetThing(string theString)
    {
        return new Thing(theString, firstDependency, secondDependency);
    }
}

Ainsi, maintenant, le consommateur de la ThingFactory peut obtenir une chose, sans avoir à connaître les dépendances de la chose, à l'exception des données de chaîne qui proviennent du consommateur.


17
Où l'implémentation concrète de GetThing () récupère-t-elle les valeurs de firstDependency et secondDependency?
Mikeyg36

88
Quelqu'un pourrait-il me dire comment cela répond à la question du PO? Cela décrit simplement ce qu'est le «modèle d'usine», puis ajoute un exemple de «méthode d'usine», qui n'est que l'un des trois «modèles d'usine». En un autre mot, je ne vois aucune comparaison nulle part.
Forethinker

4
La question d'OP mentionne clairement within an object instead of a Factory class. Je pense qu'il voulait dire le scénario où vous rendez le ctor privé et utilisez une méthode statique pour instancier la classe (créer un objet). Mais pour suivre cet exemple, il faut d'abord instancier la ThingFactoryclasse pour obtenir des Thingobjets, ce qui en fait un Factory classeffet.
atiyar

4
Désolé, mais l'explication est de la merde, car un constructeur peut également être écrit de manière à masquer les dépendances. Les informations d'arrière-plan clés que vous souhaitez séparer les informations de création de dépendance de la gestion des dépendances sont manquantes. D'ailleurs, la question concernait la même classe, la réponse n'a aucun rapport avec cela.
Christian Hujer

8
OP a demandé quand . Kyoryu a répondu comment . Bien que le style de la réponse soit louable, dans le contexte de cette question, ce n'est que du bruit.
8bitjunkie

96

Les méthodes d'usine devraient être considérées comme une alternative aux constructeurs - surtout lorsque les constructeurs ne sont pas assez expressifs, c'est-à-dire.

class Foo{
  public Foo(bool withBar);
}

n'est pas aussi expressif que:

class Foo{
  public static Foo withBar();
  public static Foo withoutBar();
}

Les classes d'usine sont utiles lorsque vous avez besoin d'un processus compliqué pour construire l'objet, lorsque la construction a besoin d'une dépendance que vous ne voulez pas pour la classe réelle, lorsque vous devez construire différents objets, etc.


2
Où est la classe Factory ici?
Koray Tugay

20
@KorayTugay: Il n'y a pas de classe d'usine, seulement des méthodes d'usine. La question est de savoir quand utiliser des méthodes d' usine au lieu d'une classe d'usine. Mais les méthodes d'usine sont plus une alternative aux constructeurs qu'une alternative aux classes d'usine. (Je ne sais pas pourquoi la meilleure réponse est si bien notée malgré le fait de ne parler que des classes d'usine).
Rasmus Faber

5
Il convient de noter que les méthodes d'usine statiques sont complètement différentes du modèle de conception Gang of Four: Factory Method.
jaco0646

76

Une situation où je trouve personnellement des classes Factory distinctes pour donner un sens est lorsque l'objet final que vous essayez de créer repose sur plusieurs autres objets. Par exemple, en PHP: Supposons que vous ayez un Houseobjet, qui à son tour a un Kitchenet un LivingRoomobjet, et que l' LivingRoomobjet ait également un TVobjet à l'intérieur.

La méthode la plus simple pour y parvenir est que chaque objet crée ses enfants sur sa méthode de construction, mais si les propriétés sont relativement imbriquées, lorsque votre Housecréation échoue, vous passerez probablement un certain temps à essayer d'isoler exactement ce qui échoue.

L'alternative est de faire ce qui suit (injection de dépendance, si vous aimez le terme de fantaisie):

$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);

Ici, si le processus de création d'un Houseéchoue, il n'y a qu'un seul endroit où chercher, mais devoir utiliser ce morceau chaque fois que l'on veut un nouveau Houseest loin d'être pratique. Entrez dans les usines:

class HouseFactory {
    public function create() {
        $TVObj = new TV($param1, $param2, $param3);
        $LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
        $KitchenroomObj = new Kitchen($param1, $param2);
        $HouseObj = new House($LivingroomObj, $KitchenroomObj);

        return $HouseObj;
    }
}

$houseFactory = new HouseFactory();
$HouseObj = $houseFactory->create();

Grâce à l'usine ici, le processus de création d'un Houseest abstrait (en ce que vous n'avez pas besoin de créer et de configurer chaque dépendance unique lorsque vous voulez simplement créer un House) et en même temps centralisé, ce qui facilite la maintenance. Il y a d'autres raisons pour lesquelles l'utilisation d'usines séparées peut être bénéfique (par exemple la testabilité) mais je trouve ce cas d'utilisation spécifique pour illustrer au mieux comment les classes d'usine peuvent être utiles.


1
Comment quelqu'un ferait-il un test unitaire à ce sujet? Je pensais que l'utilisation du "nouveau" mot clé dans une classe était considérée comme une mauvaise pratique car il ne pouvait pas être testé à l'unité. Ou est-ce qu'une usine est censée faire un peu exception à cette règle?
AgmLauncher

1
@AgmLauncher J'avais également la même question quand j'ai commencé avec les tests unitaires, consultez: stackoverflow.com/questions/10128780/…
Mahn

1
Je n'ai pas compris ça. Comment exactement les paramètres pour créer différents objets sont-ils transmis à la HouseFactoryclasse?
atiyar

1
@Mahn, ne finiriez-vous pas par avoir beaucoup de params à la fin?
Pacerier

1
@Pacerier, c'est quelque chose pour vous de décider comment modéliser, selon vos besoins, mais vous n'avez pas toujours à passer chaque paramètre à la createméthode. Par exemple, si votre Houseva toujours avoir le même type, LivingRoomil peut être judicieux de coder en dur ses paramètres dans la classe d'usine plutôt que de les passer comme arguments. Ou vous pouvez vouloir fournir un typeargument à votre HouseFactory::createméthode si vous avez quelques types de LivingRooms et avez un commutateur à l'intérieur avec les paramètres codés en dur pour chaque type.
Mahn

19

Il est important de différencier clairement l'idée derrière l'utilisation de l'usine ou de la méthode d'usine. Les deux sont destinés à résoudre différents types de problèmes de création d'objets mutuellement exclusifs.

Soyons précis sur la "méthode d'usine":

La première chose est que, lorsque vous développez une bibliothèque ou des API qui seront à leur tour utilisées pour le développement d'applications ultérieures, la méthode d'usine est l'une des meilleures sélections pour le modèle de création. Raison derrière; Nous savons que quand créer un objet avec les fonctionnalités requises, mais le type d'objet restera indécis ou il sera décidé que les paramètres dynamiques seront passés .

Maintenant, le fait est qu'environ la même chose peut être obtenue en utilisant le modèle d'usine lui-même, mais un énorme inconvénient introduira dans le système si le modèle d'usine sera utilisé pour le problème mis en évidence ci-dessus, c'est que votre logique de création d'objets différents (objets de sous-classes) être spécifique à certaines conditions commerciales, donc à l'avenir lorsque vous aurez besoin d'étendre les fonctionnalités de votre bibliothèque pour d'autres plates-formes (plus techniquement, vous devez ajouter plus de sous-classes d'interface de base ou de classe abstraite afin que l'usine renvoie également ces objets en plus de ceux existants) sur la base de certains paramètres dynamiques), puis chaque fois que vous devez modifier (étendre) la logique de la classe d'usine, ce qui sera coûteux et pas bon du point de vue de la conception. De l'autre côté, si "méthode d'usine"

interface Deliverable 
{
    /*********/
}

abstract class DefaultProducer 
{

    public void taskToBeDone() 
    {   
        Deliverable deliverable = factoryMethodPattern();
    }
    protected abstract Deliverable factoryMethodPattern();
}

class SpecificDeliverable implements Deliverable 
{
 /***SPECIFIC TASK CAN BE WRITTEN HERE***/
}

class SpecificProducer extends DefaultProducer 
{
    protected Deliverable factoryMethodPattern() 
    {
        return new SpecificDeliverable();
    }
}

public class MasterApplicationProgram 
{
    public static void main(String arg[]) 
    {
        DefaultProducer defaultProducer = new SpecificProducer();
        defaultProducer.taskToBeDone();
    }
}

15

Ils sont également utiles lorsque vous avez besoin de plusieurs "constructeurs" avec le même type de paramètre mais avec un comportement différent.


15

C'est une bonne idée d'utiliser des méthodes d'usine à l' intérieur de l'objet lorsque:

  1. La classe de l'objet ne sait pas quelles sous-classes exactes il doit créer
  2. La classe de l'objet est conçue pour que les objets qu'elle crée soient spécifiés par des sous-classes
  3. La classe de l'objet délègue ses fonctions à des sous-classes auxiliaires et ne sait pas quelle classe exacte prendra ces fonctions

C'est une bonne idée d'utiliser la classe d' usine abstraite lorsque:

  1. Votre objet ne doit pas dépendre de la façon dont ses objets internes sont créés et conçus
  2. Le groupe d'objets liés doit être utilisé ensemble et vous devez respecter cette contrainte
  3. L'objet doit être configuré par l'une des nombreuses familles possibles d'objets liés qui feront partie de votre objet parent
  4. Il est nécessaire de partager des objets enfants affichant uniquement des interfaces mais pas une implémentation

9

UML à partir de

entrez la description de l'image ici

Produit: Il définit une interface des objets créés par la méthode Factory.

ConcreteProduct: implémente l'interface produit

Créateur: déclare la méthode Factory

ConcreateCreator: implémente la méthode Factory pour renvoyer une instance d'un ConcreteProduct

Énoncé du problème: créez une usine de jeux à l'aide des méthodes d'usine, qui définissent l'interface de jeu.

Extrait de code:

import java.util.HashMap;


/* Product interface as per UML diagram */
interface Game{
    /* createGame is a complex method, which executes a sequence of game steps */
    public void createGame();
}

/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
    public Chess(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Chess game");
        System.out.println("Opponents:2");
        System.out.println("Define 64 blocks");
        System.out.println("Place 16 pieces for White opponent");
        System.out.println("Place 16 pieces for Black opponent");
        System.out.println("Start Chess game");
        System.out.println("---------------------------------------");
    }
}
class Checkers implements Game{
    public Checkers(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Checkers game");
        System.out.println("Opponents:2 or 3 or 4 or 6");
        System.out.println("For each opponent, place 10 coins");
        System.out.println("Start Checkers game");
        System.out.println("---------------------------------------");
    }
}
class Ludo implements Game{
    public Ludo(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Ludo game");
        System.out.println("Opponents:2 or 3 or 4");
        System.out.println("For each opponent, place 4 coins");
        System.out.println("Create two dices with numbers from 1-6");
        System.out.println("Start Ludo game");
        System.out.println("---------------------------------------");
    }
}

/* Creator interface as per UML diagram */
interface IGameFactory {
    public Game getGame(String gameName);
}

/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {

     HashMap<String,Game> games = new HashMap<String,Game>();
    /*  
        Since Game Creation is complex process, we don't want to create game using new operator every time.
        Instead we create Game only once and store it in Factory. When client request a specific game, 
        Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
    */

    public GameFactory(){

        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());        
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class NonStaticFactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }

        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        if ( game != null ){                    
            game.createGame();
            System.out.println("Game="+game.getClass().getName());
        }else{
            System.out.println(args[0]+  " Game does not exists in factory");
        }           
    }
}

production:

java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
Game=Chess

Cet exemple montre une Factoryclasse en implémentant un FactoryMethod.

  1. Gameest l'interface pour tous les types de jeux. Il définit une méthode complexe:createGame()

  2. Chess, Ludo, Checkers sont différentes variantes de jeux, qui permettent la mise en œuvre de createGame()

  3. public Game getGame(String gameName)est FactoryMethoden IGameFactoryclasse

  4. GameFactorypré-crée différents types de jeux dans le constructeur. Il implémente la IGameFactoryméthode d'usine.

  5. le nom du jeu est passé comme argument de ligne de commande à NotStaticFactoryDemo

  6. getGamein GameFactoryaccepte un nom de jeu et renvoie l' Gameobjet correspondant .

Usine:

Crée des objets sans exposer la logique d'instanciation au client.

FactoryMethod

Définissez une interface pour créer un objet, mais laissez les sous-classes décider de la classe à instancier. La méthode Factory permet à une classe de reporter l'instanciation aux sous-classes

Cas d'utilisation:

Quand l'utiliser: Clientne sait pas quelles classes concrètes il devra créer au moment de l'exécution, mais veut juste obtenir une classe qui fera le travail.


merci pour vous la section des keynotes, elle est concise pour moi .mais, il est inimaginable que "getArea () soit la méthode Factory dans l'interface Shape", car la méthode getArea n'instancie JAMAIS une classe, elle fait juste un calcul. interface pour créer un objet, mais laissez les sous-classes décider de la classe à instancier "s'il vous plaît.
reco

getArea()n'est pas une méthode de fabrication du tout .
Cranio

1
J'ai une opinion différente - les experts valident et mettent des notes. 1. Le client (ou l'invocateur) a besoin d'un objet d'intérêt ... il ne devrait donc pas être nécessaire d'appeler la nouvelle classe GameFactory (). La classe Factory devrait plutôt avoir une getInstance () statique. 2. Si c'est le cas, games.put (Chess.class.getName ( ), nouveau jeu d'échecs ()); retournera toujours la même référence d'échecs [si elle est implémentée comme statique] - comment gérer ce scénario de la manière la plus efficace?
Arnab Dutta

J'ai donné un exemple d'usine non statique. Vous pouvez l'implémenter avec des blocs et des méthodes statiques si vous le souhaitez. Concernant vos requêtes: 1. Le client appellera Factory pour obtenir le jeu. 2. Je mets l'objet une fois et tout Get retournera la même instance - le même referenc.e d'échecs est retourné pour chaque get
Ravindra babu

6

C'est vraiment une question de goût. Les classes d'usine peuvent être abstraites / interfacées si nécessaire, tandis que les méthodes d'usine sont plus légères (et ont également tendance à être testables, car elles n'ont pas de type défini, mais elles nécessiteront un point d'enregistrement bien connu, semblable à un service localisateur mais pour localiser les méthodes d'usine).


4

Les classes de fabrique sont utiles lorsque le type d'objet qu'elles renvoient a un constructeur privé, lorsque différentes classes de fabrique définissent des propriétés différentes sur l'objet renvoyé ou lorsqu'un type de fabrique spécifique est couplé avec son type de béton de retour.

WCF utilise les classes ServiceHostFactory pour récupérer des objets ServiceHost dans différentes situations. Le ServiceHostFactory standard est utilisé par IIS pour récupérer des instances ServiceHost pour les fichiers .svc , mais un WebScriptServiceHostFactory est utilisé pour les services qui renvoient des sérialisations aux clients JavaScript. ADO.NET Data Services a son propre DataServiceHostFactory spécial et ASP.NET a son ApplicationServicesHostFactory car ses services ont des constructeurs privés.

Si vous n'avez qu'une seule classe qui consomme l'usine, vous pouvez simplement utiliser une méthode d'usine dans cette classe.


2

Envisagez un scénario lorsque vous devez concevoir une classe Commande et Client. Pour des raisons de simplicité et d'exigences initiales, vous ne ressentez pas le besoin d'usine pour la classe Order et remplissez votre application avec de nombreuses instructions 'new Order ()'. Les choses fonctionnent bien.

Maintenant, une nouvelle exigence entre en scène: l'objet Order ne peut pas être instancié sans association Client (nouvelle dépendance). Vous avez maintenant les considérations suivantes.

1- Vous créez une surcharge de constructeur qui ne fonctionnera que pour les nouvelles implémentations. (Pas acceptable). 2- Vous modifiez les signatures Order () et modifiez chaque invocation. (Pas une bonne pratique et une vraie douleur).

Au lieu de cela, si vous avez créé une usine pour Order Class, vous n'avez qu'à modifier une ligne de code et vous êtes prêt à partir. Je suggère la classe Factory pour presque toutes les associations d'agrégats. J'espère que cela pourra aider.


1

si vous souhaitez créer un objet différent en termes d'utilisation. C'est utile.

public class factoryMethodPattern {
      static String planName = "COMMERCIALPLAN";
      static int units = 3;
      public static void main(String args[]) {
          GetPlanFactory planFactory = new GetPlanFactory();
          Plan p = planFactory.getPlan(planName);
          System.out.print("Bill amount for " + planName + " of  " + units
                        + " units is: ");
          p.getRate();
          p.calculateBill(units);
      }
}

abstract class Plan {
      protected double rate;

      abstract void getRate();

      public void calculateBill(int units) {
            System.out.println(units * rate);
      }
}

class DomesticPlan extends Plan {
      // @override
      public void getRate() {
            rate = 3.50;
      }
}

class CommercialPlan extends Plan {
      // @override
      public void getRate() {
            rate = 7.50;
      }
}

class InstitutionalPlan extends Plan {
      // @override
      public void getRate() {
            rate = 5.50;
      }
}

class GetPlanFactory {

      // use getPlan method to get object of type Plan
      public Plan getPlan(String planType) {
            if (planType == null) {
                  return null;
            }
            if (planType.equalsIgnoreCase("DOMESTICPLAN")) {
                  return new DomesticPlan();
            } else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {
                  return new CommercialPlan();
            } else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {
                  return new InstitutionalPlan();
            }
            return null;
      }
}


1

Je pense que cela dépendra du degré de couplage lâche que vous souhaitez apporter à votre code.

La méthode d'usine dissocie très bien les choses, mais la classe d'usine non.

En d'autres termes, il est plus facile de changer les choses si vous utilisez la méthode d'usine que si vous utilisez une usine simple (connue sous le nom de classe d'usine).

Regardez cet exemple: https://connected2know.com/programming/java-factory-pattern/ . Maintenant, imaginez que vous voulez amener un nouvel animal. Dans la classe Factory, vous devez changer Factory, mais dans la méthode Factory, non, vous avez seulement besoin d'ajouter une nouvelle sous-classe.


0

Les classes d'usine sont plus lourdes, mais vous offrent certains avantages. Dans les cas où vous devez créer vos objets à partir de plusieurs sources de données brutes, ils vous permettent d'encapsuler uniquement la logique de construction (et peut-être l'agrégation des données) en un seul endroit. Là, il peut être testé de manière abstraite sans se préoccuper de l'interface objet.

J'ai trouvé cela un modèle utile, en particulier lorsque je suis incapable de remplacer et d'ORM inadéquat et que je souhaite instancier efficacement de nombreux objets à partir de jointures de table DB ou de procédures stockées.


0

Je compare les usines au concept de bibliothèques. Par exemple, vous pouvez avoir une bibliothèque pour travailler avec des nombres et une autre pour travailler avec des formes. Vous pouvez stocker les fonctions de ces bibliothèques dans des répertoires logiquement nommés Numbersou Shapes. Ce sont des types génériques qui pourraient inclure des entiers, des flottants, des dobules, des longs ou des rectangles, des cercles, des triangles, des pentagones dans le cas des formes.

Le petter d'usine utilise le polymorphisme, l'injection de dépendance et l'inversion de contrôle.

Le but déclaré des modèles d'usine est: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Supposons donc que vous construisez un système d'exploitation ou une infrastructure et que vous construisez tous les composants discrets.

Voici un exemple simple du concept du Factory Pattern en PHP. Je ne suis peut-être pas à 100% sur tout cela, mais il est destiné à servir d'exemple simple. Je ne suis pas un expert.

class NumbersFactory {
    public static function makeNumber( $type, $number ) {
        $numObject = null;
        $number = null;

        switch( $type ) {
            case 'float':
                $numObject = new Float( $number );
                break;
            case 'integer':
                $numObject = new Integer( $number );
                break;
            case 'short':
                $numObject = new Short( $number );
                break;
            case 'double':
                $numObject = new Double( $number );
                break;
            case 'long':
                $numObject = new Long( $number );
                break;
            default:
                $numObject = new Integer( $number );
                break;
        }

        return $numObject;
    }
}

/* Numbers interface */
abstract class Number {
    protected $number;

    public function __construct( $number ) {
        $this->number = $number;
    }

    abstract public function add();
    abstract public function subtract();
    abstract public function multiply();
    abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Integer Implementation */
class Integer extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Short Implementation */
class Short extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Double Implementation */
class Double extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Long Implementation */
class Long extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}

$number = NumbersFactory::makeNumber( 'float', 12.5 );

Je comprends ce qui se passe ici, mais je ne comprends pas à quoi ça sert. Qu'est- NumbersFactory::makeNumber( 'float', 12.5 );ce qui me donne juste de dire new Float(12.5);si je sais que j'ai besoin d'un Float? C'est ce que je ne comprends pas des usines ... à quoi ça sert?
BadHorsie

Il vous permet de choisir différentes implémentations et ne vous lie pas à une seule. Une interface est établie et toutes les implémentations doivent la garantir et l'honorer.
Robert Rocha
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.