抽象工厂模式【Abstract Factory Pattern】实现原理?适用场景及特点?优缺点?抽象工厂模式实现?

目录


设计模式专栏目录(点击进入…)



抽象工厂模式实现原理

抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。在抽象工厂模式中,客户端不再负责对象的创建,而是把这个责任丢给了具体的工厂类,客户端只负责对对象的调用,从而明确了各个类的职责。并且当一系列相互关联的产品被设计到一个工厂类里后,客户端的调用将会变得非常简单,而且,如果要更换这一系列的产品,则只需要更换一个工厂类即可。

如果客户端需要创建一些产品结构,而这些产品结构又分别属于不同的产品类别,则可以使用抽象工厂模式,抽象工厂模式中抽象工厂类负责定义创建对象的接口,具体这一系列对象的创建工作由实现抽象工厂的具体工厂类来完成。


抽象工厂功能

抽象工厂模式的一个主要功能是它能够隔离要生成的具体产品类, 由于这些类的实际类名部被隐藏在工厂内部,因此客户端根本不需要关心如何对它们进行实例化的细节。每种设计模式都是针对特定问题的解决方案,而抽象工厂模式面临的问题则是当涉及到有多个产品等级结构,如何更好地进行软件体系结构的设计。


抽象工厂适用场景及特点

(1)多个相关的产品系列

当系统需要一次性创建一整套相关的产品时,抽象工厂模式非常有用。例如,一个图形用户界面工具包可能需要创建按钮、文本框、下拉框等各种控件,这些控件之间存在关联,可以通过抽象工厂模式统一创建。

(2)不同的产品等级结构

如果系统中存在不同的产品等级结构,而客户端需要使用一套产品族,抽象工厂模式可以提供一个统一的接口来创建不同等级结构的产品。

(3)产品变化频率低

抽象工厂模式对于产品族的变化和扩展非常友好,但对于单个产品的变化不太友好。如果产品的变化频率较低,抽象工厂模式是一个很好的选择。

(4)隐藏具体产品的实现

客户端只需要知道抽象产品的接口,而不需要关心具体产品的实现细节。这样可以降低客户端和具体产品类之间的耦合度。

(5)易于替换产品系列

由于抽象工厂模式将产品的创建封装在工厂类中,因此可以轻松替换整个产品系列,而不需要修改客户端代码。

总的来说,抽象工厂模式适合于需要创建一系列相关或相互依赖的对象,并且希望将产品的创建和使用解耦的场景。通过抽象工厂模式,可以实现产品族的扩展和替换,同时保持客户端代码的稳定性和灵活性。


抽象工厂模式的优缺点

优点

(1)产品族一致性

抽象工厂模式可以确保一次性创建一整套相关的产品,保证了这些产品之间的一致性,例如风格、主题等。

(2)易于替换产品系列

由于抽象工厂模式将产品的创建封装在工厂类中,因此可以轻松替换整个产品系列,而不需要修改客户端代码。

(3)隐藏具体产品的实现

客户端只需要知道抽象产品的接口,而不需要关心具体产品的实现细节。这样可以降低客户端和具体产品类之间的耦合度。

(4)符合开闭原则

抽象工厂模式可以轻松地添加新的产品族,而不需要修改现有的代码,符合开闭原则。

(5)提供一致的接口

抽象工厂模式提供了一致的接口来创建产品,这样可以让客户端代码更加简洁和易于维护。


缺点

(1)不易扩展产品等级结构

如果需要添加新的产品等级结构,比如增加新的按钮类型,需要修改抽象工厂接口和所有的具体工厂类,这可能会影响现有的代码。

(2)产品变化频率高

如果产品的变化频率较高,抽象工厂模式可能会导致系统变得复杂,因为每次添加新产品都需要修改抽象工厂接口和所有的具体工厂类。

(3)增加了系统的抽象性和理解难度

抽象工厂模式引入了额外的抽象层次,可能会增加系统的复杂性和理解难度。

总的来说,抽象工厂模式适合于需要创建一系列相关或相互依赖的对象,并且希望将产品的创建和使用解耦的场景。但是在产品等级结构经常变化的情况下,抽象工厂模式可能不是最佳选择。


抽象工厂模式实现

在这里插入图片描述

1、人类的接口定义

package com.uhhe.common.design.abstractfactory;

/**
 * 定义一个人类的统称
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:48
 */
public interface Human {

    /**
     * 人是愉快的,会笑的,本来是想用smile表示,想了一下laugh更合适,好长时间没有大笑了;
     */
    void laugh();

    /**
     * 人类还会哭,代表痛苦
     */
    void cry();

    /**
     * 人类会说话
     */
    void talk();

    /**
     * 定义性别
     */
    void sex();

}

2、根据接口创建三个抽象类,也就是三个产品等级,实现 laugh()、cry()、talk() 三个方法

黑色人种

package com.uhhe.common.design.abstractfactory;

/**
 * 黑色人种
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:53
 */
public abstract class AbstractBlackHuman implements Human {

    @Override
    public void laugh() {
        System.out.println("黑人会哭");
    }

    @Override
    public void cry() {
        System.out.println("黑人会笑");
    }

    @Override
    public void talk() {
        System.out.println("黑人可以说话,一般人听不懂");
    }

}

白色人种

package com.uhhe.common.design.abstractfactory;

/**
 * 白色人种
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:53
 */
public abstract class AbstractWhiteHuman implements Human {

    @Override
    public void cry() {
        System.out.println("白色人种会哭");
    }

    @Override
    public void laugh() {
        System.out.println("白色人种会大笑,侵略的笑声");
    }

    @Override
    public void talk() {
        System.out.println("白色人种会说话,一般都是但是单字节!");
    }

}

黄色人种

package com.uhhe.common.design.abstractfactory;

/**
 * 黄色人种
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:52
 */
public abstract class AbstractYellowHuman implements Human {

    @Override
    public void cry() {
        System.out.println("黄色人种会哭");
    }

    @Override
    public void laugh() {
        System.out.println("黄色人种会大笑,幸福呀!");
    }

    @Override
    public void talk() {
        System.out.println("黄色人种会说话,一般说的都是双字节");
    }

}

3、实现类(性别 + 肤色组合)

package com.uhhe.common.design.abstractfactory;

/**
 * 女性黑种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class BlackFemaleHuman extends AbstractBlackHuman {

    @Override
    public void sex() {
        System.out.println("该黑种人的性别为女...");
    }

}
package com.uhhe.common.design.abstractfactory;

/**
 * 男性黑种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class BlackMaleHuman extends AbstractBlackHuman{

    @Override
    public void sex() {
        System.out.println("该黑种人的性别为男...");
    }

}
package com.uhhe.common.design.abstractfactory;

/**
 * 女性白种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class WhiteFemaleHuman extends AbstractWhiteHuman {

    @Override
    public void sex() {
        System.out.println("该白种人的性别为女...");
    }

}
package com.uhhe.common.design.abstractfactory;

/**
 * 男性白种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class WhiteMaleHuman extends AbstractWhiteHuman{

    @Override
    public void sex() {
        System.out.println("该白种人的性别为男...");
    }

}
package com.uhhe.common.design.abstractfactory;

/**
 * 女性黄种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class YellowFemaleHuman extends AbstractYellowHuman {

    @Override
    public void sex() {
        System.out.println("该黄种人的性别为女...");
    }

}
package com.uhhe.common.design.abstractfactory;

/**
 * 男性黄种人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 13:56
 */
public class YellowMaleHuman  extends AbstractYellowHuman{

    @Override
    public void sex() {
        System.out.println("该黄种人的性别为男...");
    }

}

4、定义枚举类型(用于指定实现类)

package com.uhhe.common.design.abstractfactory;

/**
 * 世界上有哪些类型的人,列出来
 * java enum类型尽量简单使用,尽量不要使用多态、继承等方法。毕竟用class完全可以代替enum
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:30
 */
public enum HumanEnum {

    /**
     * 女性人种
     */
    YELLOW_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.YellowFemaleHuman"),
    BLACK_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.BlackFemaleHuman"),
    WHITE_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.WhiteFemaleHuman"),
    /**
     * 男性人种
     */
    YELLOW_MALE_HUMAN("com.uhhe.common.design.abstractFactory.YellowMaleHuman"),
    BLACK_MALE_HUMAN("com.uhhe.common.design.abstractFactory.BlackMaleHuman"),
    WHITE_MALE_HUMAN("com.uhhe.common.design.abstractFactory.WhiteMaleHuman");

    private String value = "";

    /**
     * 定义构造函数,目的是Data(value)类型的相匹配
     *
     * @param value 名称
     */
    private HumanEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

}

5、工厂类

工厂接口

package com.uhhe.common.design.abstractfactory;

/**
 * 接口工厂方法
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:01
 */
public interface HumanFactory {

    /**
     * 制造黄色人种
     *
     * @return Human
     */
    Human createYellowHuman();

    /**
     * 制造一个白色人种
     *
     * @return human
     */
    Human createWhiteHuman();

    /**
     * 制造一个黑色人种
     *
     * @return Human
     */
    Human createBlackHuman();

}

抽象工厂

package com.uhhe.common.design.abstractfactory;

/**
 * 编写一个抽象类,根据enum创建一个人类出来
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:34
 */
public abstract class AbstractHumanFactory implements HumanFactory {

    /**
     * 给定一个性别人种,创建一个人类出来 专业术语是产生产品等级
     *
     * @param humanEnum 人类枚举
     * @return Human
     */
    protected Human createHuman(HumanEnum humanEnum) {
        Human human = null;

        // 如果传递进来不是一个Enum中具体的一个Element的话,则不处理
        if (!humanEnum.getValue().equals("")) {
            try {
                //直接产生一个实例
                human = (Human) Class.forName(humanEnum.getValue()).newInstance();
            } catch (Exception e) {
                // 因为使用了enum,这个种异常情况不会产生了,除非enum有问题;
                e.printStackTrace();
            }
        }
        return human;
    }

}

女性创建工厂

package com.uhhe.common.design.abstractfactory;

/**
 * 女性创建工厂
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:40
 */
public class FemaleHumanFactory extends AbstractHumanFactory {

    /**
     * 创建一个女性黑种人
     *
     * @return Human
     */
    @Override
    public Human createBlackHuman() {
        return super.createHuman(HumanEnum.BLACK_FEMALE_HUMAN);
    }

    /**
     * 创建一个女性白种人
     *
     * @return Human
     */
    @Override
    public Human createWhiteHuman() {
        return super.createHuman(HumanEnum.WHITE_FEMALE_HUMAN);
    }

    /**
     * 创建一个女性黄种人
     *
     * @return Human
     */
    @Override
    public Human createYellowHuman() {
        return super.createHuman(HumanEnum.YELLOW_FEMALE_HUMAN);
    }

}

男性创建工厂

package com.uhhe.common.design.abstractfactory;

/**
 * 男性创建工厂
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:36
 */
public class MaleHumanFactory extends AbstractHumanFactory {

    /**
     * 创建一个男性黑种人
     *
     * @return Human
     */
    @Override
    public Human createBlackHuman() {
        return super.createHuman(HumanEnum.BLACK_MALE_HUMAN);
    }

    /**
     * 创建一个男性白种人
     *
     * @return Human
     */
    @Override
    public Human createWhiteHuman() {
        return super.createHuman(HumanEnum.WHITE_MALE_HUMAN);
    }

    /**
     * 创建一个男性黄种人
     *
     * @return Human
     */
    @Override
    public Human createYellowHuman() {
        return super.createHuman(HumanEnum.YELLOW_MALE_HUMAN);
    }

}

6、抽象工厂使用

package com.uhhe.common.design.abstractfactory;

/**
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 14:39
 */
public class NvWa {

    /**
     * 抽象工厂模式【Abstract Factory Pattern】
     * <p>
     * 两个八卦炉,一个造女的,一个造男的,开足马力,一直造到这个世界到现在这个模式为止。
     * <p>
     * 工厂模式有哪些优缺点?
     * 先说优点,非常重要的有点就是,工厂模式符合 OCP 原则(开闭原则,扩展开发,修改封闭),怎么说呢,比如就性别的问题,
     * <p>
     * 这个世界上还存在双性人,是男也是女的人,那这个就是要在我们的产品族中增加一类产品,
     * 同时再增加一个工厂就可以解决这个问题,不需要再来实现了吧,很简单画下类图,然后实现下。
     * <p>
     * 那还有没有其他好处呢?
     * 抽象工厂模式,还有一个非常大的有点,高内聚,低耦合,在一个较大的项目组,
     * 产品是由一批人定义开发的,但是提供其他成员访问的时候,只有工厂方法和产品的接口,
     * 也就是说只需要提供 Product Interface 和 Concrete Factory 就可以产生自己需要的对象和方法,
     * Java 的高内聚低耦合的特性表现的一览无遗
     */
    public static void main(String[] args) {
        // 第一条生产线,男性生产线
        HumanFactory maleHumanFactory = new MaleHumanFactory();
        // 第二条生产线,女性生产线
        HumanFactory femaleHumanFactory = new FemaleHumanFactory();

        // 生产线建立完毕,开始生产人了:
        Human maleYellowHuman = maleHumanFactory.createYellowHuman();
        Human femaleYellowHuman = femaleHumanFactory.createYellowHuman();

        maleYellowHuman.talk();
        maleYellowHuman.cry();
        maleYellowHuman.laugh();
        maleYellowHuman.sex();

        System.out.println("\n");

        femaleYellowHuman.talk();
        femaleYellowHuman.cry();
        femaleYellowHuman.laugh();
        femaleYellowHuman.sex();

        /*
         * .....
         */
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值