18

J'essaie de décrire succinctement quand pour utiliser une usine, pour moi-même et mon équipe. Je suis tombé sur des questions connexes suivantes, ce qui a permis un peu:Quand utiliser le motif d'usine abstrait?

Sur la base de ces liens, et un tas d'autres sources (voir la liste en bas), je suis venu avec les éléments suivants:

Quand utiliser l'abstrait modèle d'usine:

  • lorsque vous utilisez une var interface ou l'opérateur 'nouveau'
    • par exemple. Utilisateur utilisateur = new ConcreteUserImpl();
  • et le code que vous écrivez doit être testables/extensible à un moment donné

Explication:

  • interfaces par leur nature impliquent de multiples implémentations (bon pour les tests unitaires)
  • les variables d'interface impliquent le code compatible OCP et LSP (sous-classe de prise en charge)
  • utilisation de la « nouvelle » brise opérateur OCP/DI, parce que les classes très couplées sont difficiles à tester ou modifier

« Est-ce que je crée une usine pour chaque type d'objet? Cela semble excessif."

  • pas, vous pouvez avoir un (ou plusieurs) des usines qui produisent beaucoup de (généralement liés) types d'objets
  • par exemple appFactory.createUser(); appFactory.createCatalog(), etc.

Quand ne pas utiliser une usine:

  • le nouvel objet est très simple et peu susceptible d'être sous-classé
    • par exemple. Liste list = new ArrayList();
  • le nouvel objet est pas intéressant de tester
    • n'a pas de dépendances
    • N'a pas de travail pertinente ou en cours d'exécution à long
    • par exemple Logger log = nouveau SimpleLogger();

Références:


Ma question est: est mon résumé exact, et est-il logique? Y a-t-il quelque chose que j'ai oublié?

Merci d'avance.

+1

Pourquoi cette Java est-elle liée? Ne devrait-il pas être agnostique? –

+0

@the_drow: corrigé, merci. – Luke

+0

Je déteste raviver les anciens threads, mais ... Je ne suis pas d'accord que les enregistreurs doivent être nouveaux comme ci-dessus. Je cours souvent différents enregistreurs dans différents environnements de test. Je configure l'environnement pour utiliser un enregistreur spécifique et l'injecter dans les objets qui se connectent. (Je pourrais même injecter des tableaux de loggers.) – aridlehoover

Répondre

1

Résumé Le motif d'usine fournit un moyen d'encapsuler des usines concrètes qui partagent des points communs les unes avec les autres, ce qui signifie qu'elles implémentent la même interface/classe abstraite.

Vous devez utiliser le modèle d'usine lorsque vous souhaitez contrôler l'initialisation de vos objets, au lieu de donner le contrôle au consommateur.

5

Je dirais aussi ne pas utiliser une usine lorsque vous avez une implémentation particulière que vous voulez. Pour continuer l'exemple List, je sais que je veux un ArrayList parce que je fais un accès aléatoire. Je ne veux pas me fier à une usine qui a raison quand je peux le faire moi-même. Inversement, quand je ne veux pas connaître la sous-classe concrète, je peux utiliser une usine et la laisser s'inquiéter de l'objet à instancier.

Je suppose que je suggère que vous ajoutez une balle à la "quand utiliser le modèle d'usine abstraite" qui dit "et vous ne vous souciez pas vraiment quelle sous-classe concrète vous obtenez", et l'inverse de "quand pas utiliser une usine ". EDIT: Veillez à éviter le general-purpose tool-building factory factory factory.

+0

Ok - disons que je voulais les avantages spécifiques d'un pool de threads mis en cache: ExecutorService pool = Executors.newCachedThreadPool(); Cependant, dans mes tests unitaires (pour une raison quelconque) je ne suis pas intéressé par les résultats du travail effectué dans le pool, et je ne veux pas avoir à attendre que le travail se termine chaque fois que j'exécute mes tests . Est-ce que je n'utiliserais pas encore une usine pour pouvoir remplacer mon pool de threads pour des tests? Il me semble que lorsque vous envisagez de tester, vous voulez considérer ** la plupart ** de votre code comme ne se souciant pas de l'implémentation réelle de peur d'écrire du code non testable. – Luke

+0

Oui, c'est correct. Généralement, la plupart de votre code ne se soucie pas de l'implémentation réelle. Le choix entre 'ArrayList' et' LinkedList' est l'une des rares fois où vous vous en souciez, car ils ont des caractéristiques de performance différentes. Vous avez raison: pour tester, il vaut mieux ignorer l'implémentation réelle autant que possible. –

+1

+1 juste pour le lien. –

3

En général, utilisez-le lorsque vous voulez pouvoir passer de l'implémentation à une configuration externe.

JDBC et JAXP sont d'excellents exemples. Pour plus d'exemples, vérifiez this answer.

+0

Cela ne signifierait-il pas d'utiliser un conteneur IoC? – dexter

+0

@Max: pas nécessairement. – BalusC

+0

pourriez-vous préciser quand vous utiliseriez votre usine personnalisée par rapport à un IoC pour changer de type d'objet par config? – dexter