0114_抽象工厂模式 (Abstract Factory Pattern)

抽象工厂模式 (Abstract Factory Pattern)

意图

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

UML 图

AbstractFactory

优点

  1. 隔离了具体类的生成,使得客户端不需要知道什么被创建
  2. 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
  3. 增加新的具体工厂和产品族很方便,无需修改已有系统,符合"开闭原则"

缺点

  1. 增加新的产品等级结构很复杂,需要修改抽象工厂和所有具体工厂类,违背了"开闭原则"
  2. 增加了系统的抽象性和理解难度

代码示例

以下是一个扩展的抽象工厂模式示例,模拟了男性(男人、男性需要的机器人)和女性(女人、女性需要的机器人)产品族创建场景。

1. 抽象产品接口 (Abstract Product Interfaces)

// 人类接口
public interface IHuman {
    /**
     * 吃饭行为
     * 定义人类进食的基本行为
     * 该方法应由实现类具体实现进食逻辑
     */
    void eat();

}

// 机器人接口
public interface IRobot {
    /**
     * 做饭行为
     * 该方法定义了机器人执行做饭任务的标准接口
     * 具体实现由不同的机器人类型来完成
     */
    void cook();

}

2. 具体产品 (Concrete Products)

// 男人
public class HumanMan implements IHuman {
    /**
     * 人类姓名属性
     * 用于标识不同的人类个体
     */
    private String name;

    /**
     * 构造方法,用于初始化人类对象
     * @param name 人类姓名
     */
    public HumanMan(String name) {
        this.name = name;
    }

    /**
     * 实现IHuman接口的eat方法
     * 输出当前人类对象正在吃饭的信息
     * 体现了人类的基本进食行为
     */
    @Override
    public void eat() {
        System.out.println(this.name + "在吃饭");
    }

}

// 女人
public class HumanWoman implements IHuman {
    /**
     * 人类姓名属性
     * 用于标识不同的人类个体
     */
    private String name;

    /**
     * 女性人类构造方法
     * 用于创建指定姓名的女性人类对象
     * @param name 人类姓名
     */
    public HumanWoman(String name) {
        this.name = name;
    }

    /**
     * 实现IHuman接口的eat方法
     * 重写吃饭行为,输出当前女性人类对象正在吃饭的信息
     */
    @Override
    public void eat() {
        System.out.println(this.name + "在吃饭");
    }

}

// 为男人服务的机器人
public class RobotMan implements IRobot {
    /**
     * 机器人的名称属性
     * 用于标识不同的机器人实例
     */
    private String name;

    /**
     * 构造方法,用于创建RobotMan实例并初始化名称
     *
     * @param name 机器人的名称,不能为空
     */
    public RobotMan(String name) {
        this.name = name;
    }

    /**
     * 实现IRobot接口的cook方法
     * 重写父接口方法,将机器人的做饭行为作为烹饪的实现
     * 体现了多态性的应用
     */
    @Override
    public void cook() {
        System.out.println(this.name + "在做饭");
    }

}
// 为女性服务的机器人
public class RobotWoman implements IRobot {
    /**
     * 机器人的名称
     */
    private String name;

    /**
     * 构造方法,用于初始化机器人的名称
     *
     * @param name 机器人的名称
     */
    public RobotWoman(String name) {
        this.name = name;
    }

    /**
     * 实现IRobot接口的cook方法
     * 机器人通过烹饪来展示生活技能
     */
    @Override
    public void cook() {
        System.out.println(this.name + "在烹饪美食");
    }

}

3. 抽象工厂接口 (Abstract Factory Interface)

public interface IAbstractFacotory {
    /**
     * 根据名称创建具体的人类对象
     * @param name 人类名称
     * @return 对应的人类对象实例
     */
    IHuman createHuman(String name);
    
    /**
     * 根据名称创建具体的机器人对象
     * @param name 机器人名称
     * @return 对应的机器人对象实例
     */
    IRobot createRobot(String name);
}

4. 具体工厂 (Concrete Factories)

// 男性工厂
public class ManFacory implements IAbstractFacotory {

    /**
     * 根据名称创建具体的人类对象
     * @param name 人类名称
     * @return 对应的人类对象实例(HumanMan)
     */
    @Override
    public IHuman createHuman(String name) {
        return new HumanMan(name);
    }

    /**
     * 根据名称创建具体的机器人对象
     * @param name 机器人名称
     * @return 对应的机器人对象实例(RobotMan)
     */
    @Override
    public IRobot createRobot(String name) {
        return new RobotMan(name);
    }
}


// 女性工厂
public class WomanFacory implements IAbstractFacotory {

    /**
     * 根据名称创建具体的女性人类对象
     * @param name 人类名称
     * @return 对应的女性人类对象实例
     */
    @Override
    public IHuman createHuman(String name) {
        return new HumanWoman(name);
    }

    /**
     * 根据名称创建具体的女性机器人对象
     * @param name 机器人名称
     * @return 对应的女性机器人对象实例
     */
    @Override
    public IRobot createRobot(String name) {
        return new RobotWoman(name);
    }
}

5. 客户端代码 (Client Code)

public class Test {
    public static void main(String[] args) {
        // 创建男性工厂实例
        IAbstractFacotory manFacory = new ManFacory();
        // 使用男性工厂创建人类实例
        IHuman man = manFacory.createHuman("Man");
        // 使用男性工厂创建机器人实例
        IRobot manRobot = manFacory.createRobot("Man");
        // 调用机器人的cook方法
        manRobot.cook();
        // 调用人类的eat方法
        man.eat();
        
        // 创建女性工厂实例
        IAbstractFacotory womanFacory = new WomanFacory();
        // 使用女性工厂创建人类实例
        IHuman woman = womanFacory.createHuman("Woman");
        // 使用女性工厂创建机器人实例
        IRobot womanRobot = womanFacory.createRobot("Woman");
        // 调用机器人的cook方法
        womanRobot.cook();
        // 调用人类的eat方法
        woman.eat();

    }
}

在Spring框架中的应用

抽象工厂模式在Spring框架中得到了广泛应用,特别是在Bean的创建和管理方面:

  1. BeanFactory:作为Spring IoC容器的基础接口,它本身就是抽象工厂模式的体现。它定义了获取Bean的接口,而具体的实现(如DefaultListableBeanFactory, XmlBeanFactory等)负责创建和管理Bean实例。

  2. ApplicationContext:作为BeanFactory的扩展,它提供了更丰富的企业级功能,同时保持了抽象工厂的模式特性。

  3. FactoryBean接口:允许用户自定义复杂的对象创建逻辑,Spring容器会调用getObject()方法来获取实际的对象实例。

示例:

@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // 根据环境返回不同的数据源实现
        if (isProduction()) {
            return new ProductionDataSource();
        } else {
            return new DevelopmentDataSource();
        }
    }
    
    // 其他相关Bean的定义...
}

总结

抽象工厂模式通过提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,实现了产品家族的创建与使用的分离。它特别适合于需要确保一系列相关产品一起使用的场景,并且能够方便地切换整个产品家族。虽然增加新产品族很容易,但增加新产品等级结构会比较复杂,这是在使用时需要权衡的。

posted @ 2025-08-29 08:39  庞去广  阅读(10)  评论(0)    收藏  举报