JavaRush /Blog Java /Random-FR /Méthode d'usine et modèles d'usine abstraits

Méthode d'usine et modèles d'usine abstraits

Publié dans le groupe Random-FR
Dans le livre « La tête d’abord. Design Patterns » définit ces modèles comme suit : Le modèle Factory Method définit l'interface de création d'un objet, mais permet aux sous-classes de choisir la classe de l'instance à créer. Ainsi, la méthode Factory délègue l’opération d’instanciation aux sous-classes. Le modèle Abstract Factory fournit une interface pour créer des familles d'objets interdépendants ou interdépendants sans spécifier leurs classes concrètes. Essayons de comprendre cela plus en détail. Disons que vous décidez d'écrire un jeu sur des personnes qui décident de devenir... (vous avez besoin de quelque chose d'original et d'inhabituel ici) des moines. Nous pourrions commencer par ce qui suit. 1) Créez une classe Monk et des classes enfants (créons-en une d'abord) :
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2) Et bien sûr, créez une classe Monastique, dans laquelle vous pourrez mettre en œuvre des « vœux monastiques » :
public class Monastery {
    private Monk monk;

    public void createMonk(String typeName) {
        this.monk = switch (typeName) {
            case "ORTODOX" -> new OrthodoxMonk();
            default -> null;
        };
    }

    public Monk getMonk() {
        return monk;
    }
}
Eh bien, vérifions le résultat :
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
Maintenant, si vous avez besoin de créer... un moine catholique, vous devrez A) Créer une nouvelle classe pour un moine catholique :
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) Apporter des modifications à la classe du monastère :
public class Monastery {
    private Monk monk;

    public void createMonk(String typeName) {
        this.monk = switch (typeName) {
            case "ORTODOX" -> new OrthodoxMonk();
            case "CATHOLIC" -> new CatholicMonk();
            default -> null;
        };
    }

    public Monk getMonk() {
        return monk;
    }
}
et ainsi, chaque fois que de nouveaux types de moines sont introduits, vous devrez créer une nouvelle classe et modifier celle existante. Que peut-on faire dans ce cas pour « encapsuler » d'une manière ou d'une autre notre classe monastique des changements. Vous pouvez essayer d'utiliser le modèle Factory Method. A quoi cela ressemblera A) Laissons la classe des moines telle quelle, sauf peut-être en ajoutant un moine anglican (il n'y a pas que les catholiques et les chrétiens orthodoxes qui ont le monachisme) :
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
public class AnglicanMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я англиканский монах");
    }
}
B) Modifions la classe monastère comme suit (rendons-la ainsi que sa méthode abstraites). Ici, nous utilisons simplement la méthode Factory :
public abstract class Monastery {
    protected abstract Monk createMonk();
}
et créez des classes enfants avec implémentation de méthode :
public class OrthodoxMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new OrthodoxMonk();
    }
}
public class CatholicMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new CatholicMonk();
    }
}
public class AnglicanMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new AnglicanMonk();
    }
}
B) Vérifions le code
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.createMonk().description();

        monastery = new CatholicMonastery();
        monastery.createMonk().description();

        monastery = new AnglicanMonastery();
        monastery.createMonk().description();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
Ceux. comme nous le voyons maintenant, lors de l'ajout de nouveaux types de moines, il ne sera pas nécessaire de modifier les classes existantes, mais seulement si nécessaire, d'en ajouter de nouvelles (la classe d'un monastère et d'un moine spécifiques). Peut-être que quelqu'un a déjà remarqué que la méthode de description, qui était dès le début dans la classe Monk, était également Factory :) La définition de la méthode factory disait que notre modèle définit l'interface pour créer un objet, mais nous n'en avons créé aucune. interfaces, bien que nous puissions créer la classe Monastère comme interface et l'implémenter dans des implémentations spécifiques. Cela fait référence au mot « interface » dans un sens plus large. La définition indique également qu'elle permet aux sous-classes de choisir la classe de l'instance qu'elles créent . Ici, nous voyons simplement que les sous-classes (classes enfants) implémentent cette méthode (c'est-à-dire que ces pouvoirs de création d'objets moine leur sont délégués). Développons maintenant un peu notre programme, introduisons la possibilité qu'il y ait différents moines dans une dénomination ou une autre. Par exemple, dans l'Orthodoxie, sur la base de la position de l'Église orthodoxe sur les monastères et les moines (adoptée lors du Conseil des évêques de l'Église orthodoxe russe du 29 novembre au 2 décembre 2017), nous pouvons conclure qu'il existe 2 types de moines : - Petit schéma (manteau). - Schéma (grand schéma). Il existe également des « étapes préparatoires », mais les gens ne sont pas considérés comme moines (Trudnik, Novice et Ryasophor ou Moine), car ils ne prononcent pas de vœux monastiques. Nous ne les prenons donc pas en compte. Qu'obtient-on dans ce cas : A) Classe Monastère (pour simplifier, concentrons-nous pour l'instant sur le monachisme orthodoxe) avec la méthode Factory :
public abstract class Monastery {
    protected abstract Monk createMonk(String type);
}
et un monastère spécifique
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
B) Réparons la classe des moines :
public abstract class Monk {
    String kind;

    public Monk(String kind) {
        this.kind = kind;
    }

    public abstract void description();
}
et classe enfant :
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) Vérifions notre code :
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Ainsi, en utilisant le modèle Factory Method, nous avons obtenu que nous n'ayons pas besoin de modifier les classes précédemment écrites, mais également lors de l'expansion des images (types) de moines, un minimum de modifications dans le code est requis. Vérifions et ajoutons tous les ordres et congrégations de moines catholiques :) Mais il vaut mieux se concentrer sur les 3 plus connus, car il y en a plus de 100 : 1) Bénédictins 2) Jésuites 3) Franciscains Pour ce faire, comme auparavant avec le moine orthodoxe, il faut mettre en place une classe spécifique de moine catholique :
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
    }
}
et classe monastique :
public class CatholicMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
et vérifie le code :
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();

        monastery = new CatholicMonastery();
        monastery.createMonk("Бенедиктинец").description();
        monastery.createMonk("Иезуит").description();
        monastery.createMonk("Францисканец").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах - Великосхимник
Я католический монах - Бенедиктинец
Я католический монах - Иезуит
Я католический монах - Францисканец
Terminons avec ce modèle. Tous ces types de moines pourraient aussi être ajoutés à la classe E-num à l'avance, mais pour simplifier le code on s'en passera. Il est temps pour le modèle Abstract Factory. Nous avons des moines, maintenant nous pourrions leur confectionner des vêtements, des chapelets, etc. Commençons par les vêtements, c'est-à-dire que si l'on revient à notre définition du début, les vêtements deviendront une famille d'objets interconnectés ou interdépendants . Commençons par le problème que chaque type de moine a des robes différentes. Si nous ajoutons également des bouddhistes, alors ils seront complètement différents :) Pour ce faire, nous pouvons créer une interface d'usine dont les implémentations créeraient les vêtements nécessaires. Donc A) Nous créons une usine de confection de vêtements
public interface MonkFactory {
    Clothing createClothing();
}
et sa mise en œuvre
public class OrthodoxMonkFactory implements MonkFactory {

        @Override
    public Clothing createClothing() {
        return new OrtodoxClothing();
    }
}
public class CatholicMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new CatholicClothing();
    }
}
public class AnglicanMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new AnglicanClothing();
    }
}
Eh bien, n'oublions pas les moines bouddhistes :)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B) Créer une classe vestimentaire (pour simplifier, prenons l’élément clé de l’habillement des moines, nous n’entrerons pas dans les détails) :
public abstract class Clothing {
    private String name;

    public Clothing(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
et cours pour enfants
public class OrtodoxClothing extends Clothing {
    public OrtodoxClothing() {
        super("Мантия");
    }
}
public class CatholicClothing extends Clothing {
    public CatholicClothing() {
        super("Ряса с капюшоном");
    }
}
public class AnglicanClothing extends Clothing {
    public AnglicanClothing() {
        super("Ряса");
    }
}
public class BuddhistClothing extends Clothing {
    public BuddhistClothing() {
        super("Кашая");
    }
}
C) Ensuite, on change les classes des moines pour qu'ils aient des vêtements :
public abstract class Monk {
    String kind;
    Clothing clothing;

    public Monk(String kind) {
        this.kind = kind;
    }

    public void setClothing(Clothing clothing) {
        this.clothing = clothing;
    }

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class AnglicanMonk extends Monk {
    public AnglicanMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я англиканский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class BuddhistMonk extends Monk {
    public BuddhistMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я буддийский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
D) La classe monastère contient notre méthode Factory
public abstract class Monastery {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = createMonk(type);
        monk.setClothing(monkFactory.createClothing());
        return monk;
    }

    protected abstract Monk createMonk(String type);
}
nos implémentations n'ont pas changé
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
public class CatholicMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
public class AnglicanMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new AnglicanMonk(type);
    }
}
public class BuddhistMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new BuddhistMonk(type);
    }
}
D) Vérifiez le résultat :
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.create(new OrthodoxMonkFactory(), "Мантийный монах").description();

        monastery = new CatholicMonastery();
        monastery.create(new CatholicMonkFactory(), "Иезуит").description();

        monastery = new AnglicanMonastery();
        monastery.create(new AnglicanMonkFactory(), "Бенедиктинец").description();

        monastery = new BuddhistMonastery();
        monastery.create(new BuddhistMonkFactory(), "Монах").description();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
L’usine qui crée des vêtements a commencé à bien fonctionner. Vous pouvez désormais ajouter à l'usine la production de matériel pour les moines pour une prière réussie (chapelet, etc.). Mais la question demeure : est-il possible d’utiliser 2 motifs ensemble ? Bien sûr que vous pouvez :) Essayons de créer la version finale de notre projet et d'ajouter un moine hindou : A) Les usines créent désormais des moines qui sonnent comme une « usine à étoiles » :
public interface MonkFactory {
    Monk createMonk(String type);
    Clothing createClothing();
}
public class OrthodoxMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new OrthodoxMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new OrtodoxClothing();
    }
}
public class CatholicMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new CatholicMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new CatholicClothing();
    }
}
public class AnglicanMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new AnglicanMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new AnglicanClothing();
    }
}
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new BuddhistMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
public class HinduMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new HinduMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new HinduClothing();
    }
}
B) La classe monastère + les implémentations concrètes de la classe monastère ne sont pas nécessaires, elles sont mises en œuvre par l'usine (au contraire, nous pourrions les laisser et supprimer les usines, mais en substance elles seraient alors simplement à la place des usines, seulement dans dans ce cas, il faudrait alors faire du Monastère une interface, et non une classe abstraite). Et ajoutez la classe d'application :
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
B) Les moines contiennent désormais
public abstract class Monk {
    String kind;
    Clothing clothing;

    public Monk(String kind) {
        this.kind = kind;
    }

    public void setClothing(Clothing clothing) {
        this.clothing = clothing;
    }

    public abstract void description();

    public abstract void prepare(MonkFactory monkFactory);
}
contient une méthode de fabrique dans les implémentations, qui est implémentée à l'aide d'une fabrique :
public class OrthodoxMonk extends Monk {

    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class AnglicanMonk extends Monk {
    public AnglicanMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я англиканский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class BuddhistMonk extends Monk {
    public BuddhistMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я буддийский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class HinduMonk extends Monk {
    public HinduMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я индуистский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
D) Et vérifions :
public class Main {
    public static void main(String[] args) {
        Application application = new Application();

        application.create(new OrthodoxMonkFactory(), "Мантийный монах").description();
        application.create(new CatholicMonkFactory(), "Иезуит").description();
        application.create(new AnglicanMonkFactory(), "Бенедиктинец").description();
        application.create(new BuddhistMonkFactory(), "Монах").description();
        application.create(new HinduMonkFactory(), "Саньяси").description();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
En conclusion, vous pouvez noter que la méthode Factory utilisait une classe abstraite avec une méthode non implémentée, qui était implémentée dans des sous-classes, et que Abstract Factory utilisait une interface où l'implémentation (dans notre cas, la création d'un moine) se produisait dans des classes qui implémentaient cette interface.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION