281 votes

Que sont les méthodes d'usine statiques ?

Qu'est-ce qu'une méthode de "fabrique statique" ?

1 votes

Une alternative aux méthodes d'usine statique est l'utilisation de l'injection de dépendances.

2 votes

@ThangPham La réponse de Jason Owen est imparfaite parce qu'elle prétend parler du modèle Factory Method, qui est très différent du modèle statique Factory Method dont elle parle réellement. Ainsi, bien qu'elle réponde bien à la question posée, je ne pense pas qu'elle puisse être acceptée dans son état actuel, parce qu'elle introduit un modèle sans rapport et augmente la confusion déjà incroyablement courante sur la différence entre les deux modèles.

1 votes

@CMCDragonkai Je pense que l'injection de dépendance et la fabrique statique sont différentes. La fabrique statique peut être nécessaire même dans le cas de l'injection de dépendances pour instancier les dépendances à injecter.

493voto

Jason Owen Points 2279

Le site modèle de méthode d'usine statique est un moyen d'encapsuler la création d'objets. Sans une méthode de fabrique, vous appelleriez simplement la méthode de création de la classe Constructeur directement : Foo x = new Foo() . Avec ce modèle, vous feriez plutôt appel à la méthode factory : Foo x = Foo.create() . Les constructeurs sont marqués comme privés, ils ne peuvent donc être appelés que depuis l'intérieur de la classe, et la méthode d'usine est marquée comme étant static afin qu'il puisse être appelé sans avoir d'abord un objet.

Ce modèle présente quelques avantages. Le premier est que la fabrique peut choisir parmi de nombreuses sous-classes (ou implémenteurs d'une interface) et les retourner. De cette façon, l'appelant peut spécifier le comportement souhaité via des paramètres, sans avoir à connaître ou à comprendre une hiérarchie de classes potentiellement complexe.

Un autre avantage est, comme l'ont souligné Matthew et James, de contrôler l'accès à une ressource limitée telle que les connexions. C'est une façon d'implémenter des pools d'objets réutilisables - Au lieu de construire, utiliser et détruire un objet, si la construction et la destruction sont des processus coûteux, il peut être plus judicieux de les construire une fois et de les recycler. La méthode factory peut retourner un objet instancié existant et inutilisé si elle en a un, ou en construire un si le nombre d'objets est inférieur à un certain seuil, ou encore lever une exception ou renvoyer null si elle est supérieure au seuil supérieur.

Selon l'article de Wikipedia, les méthodes d'usine multiples permettent également différentes interprétations de types d'arguments similaires. Normalement, le constructeur porte le même nom que la classe, ce qui signifie que vous ne pouvez avoir qu'un seul constructeur avec une classe donnée. signature . Les usines ne sont pas aussi limitées, ce qui signifie que vous pouvez avoir deux méthodes différentes qui acceptent les mêmes types d'arguments :

Coordinate c = Coordinate.createFromCartesian(double x, double y)

et

Coordinate c = Coordinate.createFromPolar(double distance, double angle)

Cela peut également être utilisé pour améliorer la lisibilité, comme le note Rasmus.

35 votes

Notez qu'une méthode d'usine statique n'est pas la même que le motif Factory Method de Design Patterns [Gamma95, p. 107]. La méthode de fabrique statique décrite dans cet article n'a pas d'équivalent direct dans les Design Patterns.

1 votes

Ce qui m'intéresse dans cette réponse, c'est la référence aux objets partageables. C'est EXACTEMENT la façon dont j'utilise le modèle de méthode d'usine. Les méthodes d'usine sont fournies pour aider à contrôler le cycle de vie d'un objet : "create" extrait un objet du pool ou crée une nouvelle instance si le pool est vide, "destroy" le renvoie au pool pour une réutilisation ultérieure.

4 votes

Vous devriez vraiment utiliser "static factory method pattern" partout où vous dites "factory method pattern" dans ce post, vous utilisez le mauvais terme. De plus, vous faites un lien vers l'article Wikipedia sur un pattern différent de celui dont vous parlez. Le Factory Method pattern aurait probablement dû être appelé le "Factory Interface" pattern, parce qu'il implique l'utilisation de plusieurs objets factory qui implémentent une interface factory pour permettre à un seul algorithme de produire ainsi que de travailler avec des instances d'une interface, en acceptant un objet factory qui peut produire la sous-classe spécifique désirée.

174voto

Grygoriy Gonchar Points 549

NOTE ! "Le méthode d'usine statique es PAS le même que le Méthode d'usine pattern" (c) Effective Java, Joshua Bloch.

Méthode d'usine : " Définir une interface pour créer un objet, mais laisser les classes qui implémentent l'interface décider de la classe à instancier ". La méthode Factory permet à une classe de reporter l'instanciation à des sous-classes" (c) GoF.

"Une méthode de fabrique statique est simplement une méthode statique qui renvoie une instance d'une classe." (c) Effective Java, Joshua Bloch. Généralement, cette méthode se trouve à l'intérieur d'une classe particulière.

La différence :

L'idée principale de la méthode de fabrique statique est de prendre le contrôle de la création de l'objet et de le déléguer du constructeur à la méthode statique. La décision de l'objet à créer est, comme dans Abstract Factory, prise en dehors de la méthode (dans le cas courant, mais pas toujours). Alors que l'idée clé ( !) de la méthode Factory est de déléguer la décision de quelle instance de classe créer à l'intérieur de la méthode Factory. Par exemple, la mise en œuvre classique de Singleton est un cas particulier de méthode de fabrique statique. Exemple de méthodes d'usine statiques couramment utilisées :

  • valeurOf
  • getInstance
  • newInstance

0 votes

Pouvez-vous me dire la différence entre new A() et A.newInstance() ? et dans A.newInstance que devons-nous faire ?

0 votes

En général, lorsque vous avez une méthode statique comme newInstance, le constructeur est privé et vous ne pouvez pas créer d'objet avec new A(). Dans ce cas, vous rendez la méthode newInstance statique et publique et vous retournez l'objet new A() avec cette méthode. P.S. Je sais que je suis en retard pour répondre à cette question.

136voto

Matthew Flaschen Points 131723

Nous évitons de fournir un accès direct aux connexions aux bases de données car elles sont gourmandes en ressources. Nous utilisons donc une méthode d'usine statique getDbConnection qui crée une connexion si on est en dessous de la limite. Sinon, il essaie de fournir une connexion "de réserve", et échoue avec une exception s'il n'y en a pas.

public class DbConnection{
   private static final int MAX_CONNS = 100;
   private static int totalConnections = 0;

   private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

   private DbConnection(){
     // ...
     totalConnections++;
   }

   public static DbConnection getDbConnection(){

     if(totalConnections < MAX_CONNS){
       return new DbConnection();

     }else if(availableConnections.size() > 0){
         DbConnection dbc = availableConnections.iterator().next();
         availableConnections.remove(dbc);
         return dbc;

     }else {
         throw new NoDbConnections();
     }
   }

   public static void returnDbConnection(DbConnection dbc){
     availableConnections.add(dbc);
     //...
   }
}

0 votes

Si je comprends bien, pouvez-vous ajouter availableConnections.add(db) à la méthode returnDbConnection(DbConnection db) ?

0 votes

@haifzhan, ce n'est pas vraiment prévu pour être complet, mais ok.

0 votes

@MatthewFlaschen le totalConnections doit-il être décrémenté lorsque la connexion est renvoyée ?

70voto

Rasmus Faber Points 24195

La lisibilité peut être améliorée par des méthodes d'usine statiques :

Comparez

public class Foo{
  public Foo(boolean withBar){
    //...
  }
}

//...

// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.

à

public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();

0 votes

J'ai donc essayé de mettre en œuvre votre exemple mais je ne suis pas sûr de savoir comment cela fonctionne. Est-ce que les deux méthodes createWithBar et createWithoutBar sont censées appeler deux constructeurs privés dans la classe Foo ?

0 votes

@Baxtex : Oui. Chacun appellera un constructeur privé. Peut-être juste le même : private Foo(boolean withBar){/*..*/} public static Foo createWithBar(){return new Foo(true);} public static Foo createWithoutBar(){return new Foo(false);}

0 votes

Je pense que ce n'est pas très "échelle". Si vous avez trois paramètres ou plus, comment pouvez-vous utiliser cette idée et créer un nom sympa pour la méthode ?

22voto

soldier.moth Points 8996
  • ont des noms, contrairement aux constructeurs, ce qui peut clarifier le code.
  • n'ont pas besoin de créer un nouvel objet à chaque invocation - les objets peuvent être mis en cache et réutilisés, si nécessaire.
  • peuvent retourner un sous-type de leur type de retour - en particulier, peut retourner un objet dont la classe d'implémentation est inconnue de l'appelant. Il s'agit d'une fonctionnalité très précieuse et largement utilisée dans de nombreux frameworks qui utilisent des interfaces comme type de retour des méthodes de fabrique statiques.

de http://www.javapractices.com/topic/TopicAction.do?Id=21

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X