JavaRush /Java 博客 /Random-ZH /工厂方法和抽象工厂模式

工厂方法和抽象工厂模式

已在 Random-ZH 群组中发布
在《头第一。《设计模式》对这些模式的定义如下: 工厂方法模式定义了用于创建对象的接口,但允许子类选择要创建的实例的类。因此,Factory方法将实例化操作委托给子类。抽象工厂模式提供了一个接口,用于创建一系列相互关联或相互依赖的对象,而无需指定它们的具体类。 让我们尝试更详细地了解这一点。假设您决定编写一款关于那些决定成为…… (您需要一些原创且不寻常的东西)僧侣的游戏。我们可以从以下几点入手。1)创建Monk类和子类(我们先创建一个):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2)当然,创建一个 Monastery 类,您可以在其中实现“修道院誓言”:
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;
    }
}
好吧,让我们检查一下结果:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
现在,如果您需要创建...一个天主教僧侣,您将需要 A) 为天主教僧侣创建一个新类:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) 对修道院类进行更改:
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;
    }
}
因此,每次引入新类型的僧侣时,您都必须创建一个新类别并编辑现有类别。 在这种情况下可以做些什么来以某种方式“封装”我们的修道院类免受更改。您可以尝试使用工厂方法模式。 A) 让我们保留僧侣阶层不变,除了添加一个英国圣公会僧侣(不仅天主教徒和东正教基督徒有修道院制度):
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) 让我们按如下方式更改 monastery 类(让我们将其及其方法抽象化)。这里我们只使用Factory方法:
public abstract class Monastery {
    protected abstract Monk createMonk();
}
并创建具有方法实现的子类:
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) 让我们检查一下代码
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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
那些。正如我们现在所看到的,当添加新的僧侣类别时,不需要更改现有的类别,而只有在必要时才添加新的类别(特定寺院和僧侣的类别)。也许有人已经注意到了,Monk类中一开始就有的description方法也是Factory :)工厂方法的定义说的是我们的模式定义了创建对象的接口,但是我们并没有创建任何对象接口,尽管我们可以将 Monastery 类创建为接口并在特定实现中实现它。这是指更广泛意义上的“接口”一词。该定义还表示, 它允许子类选择它们创建的实例的类。这里我们只是看到子类(子类)实现了这个方法(也就是将这些创建monk对象的权力委托给了它们)。现在让我们稍微扩展一下我们的程序,介绍一个教派或另一个教派中存在不同僧侣的可能性。例如,在东正教中,根据东正教对修道院和修道院的立场(2017年11月29日至12月2日俄罗斯东正教主教理事会通过),我们可以得出结论,僧侣有两种类型: - 较小的架构(地幔)。- 模式(伟大的模式)。还有“预备阶段”,但人们不被视为僧侣(Trudnik、Novice 和 Ryasophor 或 Monk),因为他们不发修道院誓言。因此,我们不考虑它们。在这种情况下我们会得到什么:A)带有工厂方法的Monastery 类(为了简单起见,现在让我们关注东正教修道院主义):
public abstract class Monastery {
    protected abstract Monk createMonk(String type);
}
和一个特定的修道院
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
B) 让我们修复僧侣类:
public abstract class Monk {
    String kind;

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

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

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) 让我们检查一下我们的代码:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
因此,通过使用Factory Method模式,我们实现了不必更改以前编写的类,而且在扩展僧人图像(类型)时,只需要最少的代码更改。让我们检查并添加天主教僧侣的所有命令和会众 :) 但最好关注 3 个最著名的,因为其中有超过 100 个: 1) 本笃会 2) 耶稣会 3) 方济各会 要做到这一点,就像以前一样对于东正教僧侣,我们需要实现一个特定的天主教僧侣类:
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

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

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
并检查代码:
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();
    }
}
Я православный монах - Мантийный монах
Я православный монах - Великосхимник
Я католический монах - Бенедиктинец
Я католический монах - Иезуит
Я католический монах - Францисканец
让我们以这个模式结束。 所有这些类型的僧侣也可以提前添加到 E-num 类中,但为了简化代码,我们将不这样做。 现在是抽象工厂模式的时候了。我们有和尚,现在我们可以给他们做衣服、念珠等等。我们先从服装开始,也就是说,如果回到我们一开始的定义, 服装将成为一个相互关联或相互依存的物体家族。我们先来说说每种僧人的袈裟不同的问题。如果我们还添加佛教,那么它们将完全不同:) 为此,我们可以创建一个工厂接口,其实现将创建必要的衣服。因此 A) 我们创建一家制造衣服的工厂
public interface MonkFactory {
    Clothing createClothing();
}
及其实施
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();
    }
}
好吧,我们不要忘记佛教僧侣:)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B)创建服装类(为了简单起见,我们以僧侣服装为关键元素,不再赘述):
public abstract class Clothing {
    private String name;

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

    public String getName() {
        return name;
    }
}
和儿童班
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) 接下来,我们改变僧侣的等级,让他们有衣服:
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) monastery类包含我们的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);
}
我们的实施没有改变
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) 检查结果:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
生产服装的工厂已经开始运转良好。现在您可以在工厂中添加僧侣成功祈祷所需的设备(念珠等)的生产。但问题仍然存在,是否可以同时使用两种模式?当然可以:)让我们尝试制作我们项目的最终版本并添加一个印度教僧侣:A)现在创建僧侣的工厂听起来像一个“明星工厂”
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)不需要 monastery 类 + Monastery 类的具体实现,它们是由工厂实现的(相反,我们可以保留它们并删除工厂,但本质上它们只是简单地代替工厂,仅在在这种情况下,修道院必须成为一个接口,而不是抽象类)。并添加应用程序类:
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
B) 僧侣现在包含
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);
}
实现中包含一个工厂方法,它是使用工厂来实现的:
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) 让我们检查一下:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
总之,您可以注意到工厂方法使用了一个带有未实现方法的抽象类,该方法在子类中实现,而抽象工厂使用了一个接口,其中实现(在我们的例子中是创建一个僧侣)发生在实现了的类中这个界面。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION