CodeGym/Blog Java/Random-FR/Modèles de conception : méthode d'usine
Auteur
Andrey Gorkovenko
Frontend Engineer at NFON AG

Modèles de conception : méthode d'usine

Publié dans le groupe Random-FR
membres
Salut! Aujourd'hui, nous allons continuer à étudier les modèles de conception et nous discuterons du modèle de méthode d'usine. Modèles de conception : méthode d'usine - 1 Vous découvrirez de quoi il s'agit et à quelles tâches ce modèle convient. Nous allons considérer ce modèle de conception dans la pratique et étudier sa structure. Pour vous assurer que tout est clair, vous devez comprendre les sujets suivants :
  1. Héritage en Java.
  2. Méthodes abstraites et classes en Java

Quel problème la méthode de l'usine résout-elle ?

Tous les modèles de conception d'usine ont deux types de participants : les créateurs (les usines elles-mêmes) et les produits (les objets créés par les usines). Imaginez la situation suivante : nous avons une usine qui produit des voitures de marque CodeGym. Il sait créer des modèles de voitures avec différents types de carrosseries :
  • berlines
  • breaks
  • coupés
Notre entreprise a tellement prospéré qu'un beau jour, nous avons acquis un autre constructeur automobile, OneAuto. En tant qu'entrepreneurs sensés, nous ne voulons perdre aucun client OneAuto, et nous sommes donc confrontés à la tâche de restructurer la production afin de pouvoir produire :
  • Berlines CodeGym
  • Les breaks CodeGym
  • Coupés CodeGym
  • Berlines OneAuto
  • Les breaks OneAuto
  • Coupés OneAuto
Comme vous pouvez le voir, au lieu d'un groupe de produits, nous en avons maintenant deux, et ils diffèrent par certains détails. Le modèle de conception de la méthode d'usine est utilisé lorsque nous devons créer différents groupes de produits, chacun ayant des caractéristiques spécifiques. Nous allons mettre en pratique le principe directeur de ce modèle, en passant progressivement du simple au complexe, en prenant l'exemple de notre café, que nous avons créé dans l'une des leçons précédentes .

Un peu sur le modèle d'usine

Permettez-moi de vous rappeler que nous avons précédemment construit un petit café virtuel. Avec l'aide d'une usine simple, nous avons appris à créer différents types de café. Aujourd'hui, nous allons retravailler cet exemple. Rappelons-nous à quoi ressemblait notre café, avec sa simple usine. Nous avons eu un cours de café:
public class Coffee {
    public void grindCoffee(){
        // Grind the coffee
    }
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
Et plusieurs classes enfants correspondant à des types de café spécifiques que notre usine pourrait produire :
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Nous avons créé une énumération pour faciliter la passation de commandes :
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
L'usine de café elle-même ressemblait à ceci :
public class SimpleCoffeeFactory {
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new Americano();
                break;
            case ESPRESSO:
                coffee = new Espresso();
                break;
            case CAPPUCCINO:
                coffee = new Cappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

        return coffee;
    }
}
Et enfin, le café lui-même ressemblait à ceci :
public class CoffeeShop {

    private final SimpleCoffeeFactory coffeeFactory;

    public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
        this.coffeeFactory = coffeeFactory;
    }

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = coffeeFactory.createCoffee(type);
        coffee.grindCoffee();
        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }
}

Moderniser une usine simple

Notre café fonctionne très bien. A tel point que nous envisageons de nous agrandir. Nous souhaitons ouvrir de nouveaux sites. Nous sommes audacieux et entreprenants, nous ne créerons donc pas de cafés ennuyeux. Nous voulons que chaque magasin ait une touche spéciale. Ainsi, dans un premier temps, nous ouvrirons deux sites : un italien et un américain. Ces changements affecteront non seulement le design intérieur, mais également les boissons proposées :
  • dans le café italien, nous utiliserons exclusivement des marques de café italiennes, avec une mouture et une torréfaction spéciales.
  • l'emplacement américain aura de plus grandes portions, et nous servirons des guimauves avec chaque commande.
La seule chose qui reste inchangée est notre modèle économique, qui s'est avéré excellent. En termes de code, c'est ce qui se passe. Nous avions 4 classes correspondant à nos produits :
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Mais maintenant nous en aurons 8 :
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}

public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Puisque nous voulons conserver le modèle économique actuel, nous voulons que la orderCoffee(CoffeeType type)méthode subisse le moins de changements possible. Jetez un coup d'oeil:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Here's your coffee! Thanks! Come again!");
    return coffee;
}
Quelles options avons-nous? Eh bien, nous savons déjà comment écrire une usine, non ? La chose la plus simple qui nous vient immédiatement à l'esprit est d'écrire deux usines similaires, puis de transmettre l'implémentation souhaitée au constructeur de notre café. En faisant cela, la classe du café ne changera pas. Tout d'abord, nous devons créer une nouvelle classe de fabrique, lui faire hériter de notre fabrique simple, puis remplacer la createCoffee(CoffeeType type)méthode. Écrivons des usines pour créer du café à l'italienne et du café à l'américaine :
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {

    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}

public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }

}
Nous pouvons maintenant transmettre l'implémentation d'usine souhaitée à CoffeeShop. Voyons à quoi ressemblerait le code pour commander du café dans différents cafés. Par exemple, cappuccino à l'italienne et à l'américaine :
public class Main {
    public static void main(String[] args) {
        /*
            Order an Italian-style cappuccino:
            1. Create a factory for making Italian coffee
            2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
        CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
        italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);


         /*
            Order an American-style cappuccino
            1. Create a factory for making American coffee
            2. Create a new coffee shop, passing the American coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
        CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
        americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
    }
}
Nous avons créé deux cafés différents, en passant l'usine souhaitée à chacun. D'un côté, nous avons atteint notre objectif, mais de l'autre... D'une certaine manière, cela ne plaît pas aux entrepreneurs... Voyons ce qui ne va pas. Premièrement, l'abondance des usines. Quoi? Maintenant, pour chaque nouvel emplacement, nous sommes censés créer sa propre usine et, en plus, nous assurer que l'usine concernée est transmise au constructeur lors de la création d'un café ? Deuxièmement, c'est encore une simple usine. Juste modernisé légèrement. Mais nous sommes ici pour apprendre un nouveau modèle. Troisièmement, une approche différente n'est-elle pas possible ? Ce serait formidable si nous pouvions mettre tous les problèmes liés à la préparation du café dans leCoffeeShopclasse en reliant les processus de création de café et de service des commandes, tout en conservant simultanément une flexibilité suffisante pour préparer différents styles de café. La réponse est oui, nous le pouvons. C'est ce qu'on appelle le modèle de conception de méthode d'usine.

D'une simple usine à une méthode d'usine

Pour résoudre la tâche le plus efficacement possible :
  1. Nous renvoyons la createCoffee(CoffeeType type)méthode à la CoffeeShopclasse.
  2. Nous rendrons cette méthode abstraite.
  3. La CoffeeShopclasse elle-même deviendra abstraite.
  4. La CoffeeShopclasse aura des classes enfants.
Oui ami. Le café italien n'est rien d'autre qu'un descendant de la CoffeeShopclasse, qui met en œuvre la createCoffee(CoffeeType type)méthode dans le respect des meilleures traditions des baristas italiens. Maintenant, une étape à la fois. Étape 1. Rendre la Coffeeclasse abstraite. Nous avons deux familles entières de produits différents. Pourtant, les cafés italiens et américains ont un ancêtre commun : la Coffeeclasse. Il conviendrait de le rendre abstrait :
public abstract class Coffee {
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
Étape 2. Rendre CoffeeShopabstrait, avec une createCoffee(CoffeeType type)méthode abstraite
public abstract class CoffeeShop {

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);

        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }

    protected abstract Coffee createCoffee(CoffeeType type);
}
Étape 3. Créez un café italien, qui est un descendant du café abstrait. Nous y implémentons la createCoffee(CoffeeType type)méthode en tenant compte des spécificités des recettes italiennes.
public class ItalianCoffeeShop extends CoffeeShop {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}
Étape 4. Nous faisons la même chose pour le café à l'américaine
public class AmericanCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }
}
Étape 5. Découvrez à quoi ressembleront les lattes américains et italiens :
public class Main {
    public static void main(String[] args) {
        CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
        italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);

        CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
        americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
    }
}
Toutes nos félicitations. Nous venons d'implémenter le modèle de conception de la méthode d'usine en utilisant notre café comme exemple.

Le principe des méthodes d'usine

Examinons maintenant plus en détail ce que nous avons obtenu. Le schéma ci-dessous montre les classes résultantes. Les blocs verts sont des classes de créateurs et les blocs bleus sont des classes de produits. Modèles de conception : méthode d'usine - 2Quelles conclusions pouvons-nous tirer ?
  1. Tous les produits sont des implémentations de la Coffeeclasse abstraite.
  2. Tous les créateurs sont des implémentations de la CoffeeShopclasse abstraite.
  3. Nous voyons deux hiérarchies de classes parallèles :
    • Hiérarchie des produits. On voit des descendants italiens et des descendants américains
    • Hiérarchie des créateurs. On voit des descendants italiens et des descendants américains
  4. La CoffeeShopsuperclasse n'a aucune information sur le produit spécifique ( Coffee) qui sera créé.
  5. La CoffeeShopsuperclasse délègue la création d'un produit spécifique à ses descendants.
  6. Chaque descendant de la CoffeeShopclasse implémente une createCoffee()méthode de fabrique selon ses propres spécificités. En d'autres termes, les implémentations des classes de producteurs préparent des produits spécifiques basés sur les spécificités de la classe de producteurs.
Vous êtes maintenant prêt pour la définition du modèle de méthode d'usine . Le modèle de méthode d'usine définit une interface pour créer un objet, mais permet aux sous-classes de sélectionner la classe de l'objet créé. Ainsi, une méthode de fabrique délègue la création d'une instance à des sous-classes. En général, se souvenir de la définition n'est pas aussi important que de comprendre comment tout cela fonctionne.

Structure d'une méthode d'usine

Modèles de conception : méthode d'usine - 3Le diagramme ci-dessus montre la structure générale du modèle de méthode d'usine. Quoi d'autre est important ici?
  1. La classe Creator implémente toutes les méthodes qui interagissent avec les produits, à l'exception de la méthode factory.
  2. La méthode abstraite factoryMethod()doit être implémentée par tous les descendants de la Creatorclasse.
  3. La ConcreteCreatorclasse implémente la factoryMethod()méthode, qui crée directement le produit.
  4. Cette classe est responsable de la création de produits spécifiques. C'est la seule classe avec des informations sur la création de ces produits.
  5. Tous les produits doivent implémenter une interface commune, c'est-à-dire qu'ils doivent être des descendants d'une classe de produits commune. Cela est nécessaire pour que les classes qui utilisent des produits puissent fonctionner dessus comme des abstractions, plutôt que comme des implémentations spécifiques.

Devoirs

Aujourd'hui, nous avons beaucoup travaillé et étudié le modèle de conception de la méthode d'usine. Il est temps de renforcer le matériel ! Exercice 1. Faites le travail pour ouvrir un autre café. Il peut s'agir d'un café de style anglais ou de style espagnol. Ou même de style vaisseau spatial. Ajoutez du colorant alimentaire au café pour le faire briller, et votre café sera tout simplement hors de ce monde ! Exercice 2. Dans la dernière leçon , vous avez fait un exercice où vous avez créé un bar à sushi virtuel ou une pizzeria virtuelle. Maintenant, votre exercice consiste à ne pas rester immobile. Aujourd'hui, vous avez appris à utiliser le modèle de méthode d'usine à votre avantage. Il est temps d'utiliser ces connaissances et de développer votre propre entreprise ;)
Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires