在软件开发中,工厂模式(Factory Pattern) 是一种常用的创建型设计模式,其核心思想是“封装对象的创建过程”,通过一个统一的“工厂”类来生成目标对象,而非让客户端(调用代码)直接使用 new 关键字创建。这样可以降低客户端与具体产品类的耦合度,提高代码的灵活性、可维护性和可扩展性。

一、为什么需要工厂模式?(解决的核心问题)

在没有工厂模式时,客户端通常直接依赖具体产品类,例如:

// 客户端直接创建具体产品对象,耦合度高
Phone apple = new IPhone();
Phone huawei = new HuaweiPhone();

这种方式存在明显缺陷:

  1. 耦合度高:客户端必须知道所有具体产品类的存在(如 IPhoneHuaweiPhone),一旦产品类名修改或新增产品,客户端代码需要大量修改。
  2. 创建逻辑复杂:若对象创建需要复杂的初始化(如配置参数、依赖注入、校验逻辑),这些逻辑会散落在客户端,导致代码冗余且难以维护。
  3. 扩展性差:新增产品时,需在所有创建对象的地方添加 new 语句,违反“开闭原则”(对扩展开放、对修改关闭)。

工厂模式通过引入“工厂”作为中间层,将“对象创建”与“对象使用”分离,完美解决上述问题。

二、工厂模式的3种核心实现形式

根据复杂度和适用场景,工厂模式分为 简单工厂模式工厂方法模式抽象工厂模式,三者的抽象程度和灵活性依次递增。

1. 简单工厂模式(Simple Factory Pattern)

又称“静态工厂模式”,是工厂模式的基础形式——通过一个单一工厂类,根据客户端传入的“参数”动态创建不同的具体产品对象。

结构组成

角色

职责描述

抽象产品(Product)

定义所有具体产品的公共接口或抽象类(如 Phone),规范产品的核心行为。

具体产品(Concrete Product)

实现抽象产品接口的具体类(如 IPhoneHuaweiPhone),包含实际业务逻辑。

工厂类(Factory)

提供静态方法(或实例方法),根据参数判断并创建对应的具体产品对象。

代码示例(Java)
// 1. 抽象产品:定义手机的公共行为
interface Phone {
    void makeCall(); // 打电话(核心功能)
}

// 2. 具体产品1:iPhone实现
class IPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用iPhone打电话");
    }
}

// 2. 具体产品2:华为手机实现
class HuaweiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用华为手机打电话");
    }
}

// 3. 简单工厂类:根据参数创建具体产品
class PhoneFactory {
    // 静态方法:接收产品类型参数,返回对应的Phone对象
    public static Phone createPhone(String type) {
        switch (type) {
            case "iPhone":
                return new IPhone(); // 创建iPhone
            case "Huawei":
                return new HuaweiPhone(); // 创建华为手机
            default:
                throw new IllegalArgumentException("未知的手机类型:" + type);
        }
    }
}

// 客户端使用:无需直接new具体产品,只需调用工厂
public class Client {
    public static void main(String[] args) {
        Phone apple = PhoneFactory.createPhone("iPhone");
        Phone huawei = PhoneFactory.createPhone("Huawei");
        
        apple.makeCall(); // 输出:用iPhone打电话
        huawei.makeCall(); // 输出:用华为手机打电话
    }
}
优缺点
  • 优点:客户端无需关心产品创建细节,只需传入参数即可获取对象,降低耦合。
  • 缺点:工厂类承担了所有产品的创建逻辑,一旦新增产品(如 XiaomiPhone),必须修改工厂类的 switch 逻辑,违反“开闭原则”,适合产品种类较少且稳定的场景。

2. 工厂方法模式(Factory Method Pattern)

为解决简单工厂模式的“开闭原则”问题,工厂方法模式将“单一工厂”拆分为“多个具体工厂”——每个具体产品对应一个专属的具体工厂,新增产品时只需新增对应的工厂类,无需修改原有代码。

结构组成

角色

职责描述

抽象产品(Product)

同简单工厂,定义具体产品的公共接口(如 Phone)。

具体产品(Concrete Product)

同简单工厂,实现抽象产品(如 IPhoneHuaweiPhone)。

抽象工厂(Abstract Factory)

定义工厂的公共接口,包含一个创建产品的抽象方法(如 createPhone())。

具体工厂(Concrete Factory)

实现抽象工厂接口,负责创建对应的具体产品(如 IPhoneFactory 对应 IPhone)。

代码示例(Java)
// 1. 抽象产品:Phone
interface Phone {
    void makeCall();
}

// 2. 具体产品:IPhone、HuaweiPhone(同简单工厂)
class IPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用iPhone打电话");
    }
}
class HuaweiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用华为手机打电话");
    }
}

// 3. 抽象工厂:定义创建Phone的接口
interface PhoneFactory {
    Phone createPhone(); // 抽象方法:创建手机
}

// 4. 具体工厂1:IPhoneFactory(专属创建IPhone)
class IPhoneFactory implements PhoneFactory {
    @Override
    public Phone createPhone() {
        return new IPhone();
    }
}

// 4. 具体工厂2:HuaweiFactory(专属创建HuaweiPhone)
class HuaweiFactory implements PhoneFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone();
    }
}

// 客户端使用:通过具体工厂获取产品
public class Client {
    public static void main(String[] args) {
        // 1. 创建对应工厂
        PhoneFactory appleFactory = new IPhoneFactory();
        PhoneFactory huaweiFactory = new HuaweiFactory();
        
        // 2. 工厂创建产品
        Phone apple = appleFactory.createPhone();
        Phone huawei = huaweiFactory.createPhone();
        
        apple.makeCall(); // 用iPhone打电话
        huawei.makeCall(); // 用华为手机打电话
    }
}
新增产品的扩展(符合开闭原则)

若新增 XiaomiPhone,只需两步:

  1. 新增具体产品类 XiaomiPhone implements Phone
  2. 新增具体工厂类 XiaomiFactory implements PhoneFactory
    无需修改任何原有代码,完全符合“开闭原则”。
优缺点
  • 优点:遵循开闭原则,扩展性强;每个工厂只负责一种产品,职责单一(符合“单一职责原则”)。
  • 缺点:产品与工厂一一对应,新增产品时会导致工厂类数量激增(如10种产品对应10个工厂),增加代码复杂度。

3. 抽象工厂模式(Abstract Factory Pattern)

当系统需要创建“一系列相关或相互依赖的产品族”时(而非单一产品),工厂方法模式已无法满足,此时需要抽象工厂模式。例如:手机工厂不仅生产手机(Phone),还生产耳机(Earphone)——IPhoneAirPods 是一个产品族,HuaweiPhoneHuaweiEarphone 是另一个产品族。

抽象工厂模式的核心是“创建产品族”,而非单一产品。

结构组成

角色

职责描述

抽象产品族(Product Family)

一组相关的抽象产品(如 PhoneEarphone),定义产品族的所有成员。

具体产品(Concrete Product)

属于某个产品族的具体实现(如 IPhoneAirPodsHuaweiEarphone)。

抽象工厂(Abstract Factory)

定义创建“产品族所有成员”的抽象方法(如 createPhone()createEarphone())。

具体工厂(Concrete Factory)

实现抽象工厂,负责创建“某一产品族”的所有具体产品(如 AppleFactory 生产 IPhoneAirPods)。

代码示例(Java)
// 1. 抽象产品族1:Phone
interface Phone {
    void makeCall();
}
// 1. 抽象产品族2:Earphone
interface Earphone {
    void playMusic();
}

// 2. 具体产品(Apple产品族)
class IPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用iPhone打电话");
    }
}
class AirPods implements Earphone {
    @Override
    public void playMusic() {
        System.out.println("用AirPods听音乐");
    }
}

// 2. 具体产品(Huawei产品族)
class HuaweiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用华为手机打电话");
    }
}
class HuaweiEarphone implements Earphone {
    @Override
    public void playMusic() {
        System.out.println("用华为耳机听音乐");
    }
}

// 3. 抽象工厂:定义创建产品族的接口(Phone + Earphone)
interface ElectronicFactory {
    Phone createPhone();     // 创建手机
    Earphone createEarphone(); // 创建耳机
}

// 4. 具体工厂1:AppleFactory(生产Apple产品族)
class AppleFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new IPhone();
    }
    @Override
    public Earphone createEarphone() {
        return new AirPods();
    }
}

// 4. 具体工厂2:HuaweiFactory(生产Huawei产品族)
class HuaweiFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone();
    }
    @Override
    public Earphone createEarphone() {
        return new HuaweiEarphone();
    }
}

// 客户端使用:通过具体工厂获取整个产品族
public class Client {
    public static void main(String[] args) {
        // 1. 选择Apple产品族工厂
        ElectronicFactory appleFactory = new AppleFactory();
        Phone applePhone = appleFactory.createPhone();
        Earphone appleEarphone = appleFactory.createEarphone();
        
        applePhone.makeCall();       // 用iPhone打电话
        appleEarphone.playMusic();   // 用AirPods听音乐
        
        // 2. 选择Huawei产品族工厂
        ElectronicFactory huaweiFactory = new HuaweiFactory();
        Phone huaweiPhone = huaweiFactory.createPhone();
        Earphone huaweiEarphone = huaweiFactory.createEarphone();
        
        huaweiPhone.makeCall();      // 用华为手机打电话
        huaweiEarphone.playMusic();  // 用华为耳机听音乐
    }
}
优缺点
  • 优点:保证同一产品族的产品“一致性”(如 AppleFactory 不会生产 HuaweiEarphone);新增产品族时只需新增具体工厂,符合开闭原则。
  • 缺点:新增“产品族的成员”(如在 ElectronicFactory 中新增 Tablet 平板)时,需修改所有抽象工厂和具体工厂的代码,违反开闭原则(即“产品族稳定,但产品族成员难扩展”)。

三、3种工厂模式的对比与选择

维度

简单工厂模式

工厂方法模式

抽象工厂模式

核心能力

单一工厂创建多种产品

一个产品对应一个工厂

创建“产品族”(多产品组合)

开闭原则

违反(新增产品需改工厂)

符合(新增产品+新增工厂)

部分符合(新增产品族符合,新增产品成员违反)

代码复杂度

低(仅1个工厂)

中(产品数=工厂数)

高(需设计产品族和工厂)

适用场景

产品少且稳定(如工具类)

产品多变但独立(如插件)

需统一产品族(如品牌套件:手机+耳机+平板)

四、工厂模式的核心价值总结

  1. 解耦:分离“对象创建”与“对象使用”,客户端无需依赖具体产品类,只需依赖工厂和抽象产品。
  2. 可维护:对象创建逻辑集中在工厂,修改时只需改工厂,无需改所有客户端。
  3. 可扩展:新增产品时,简单工厂需修改,工厂方法和抽象工厂只需新增类(符合开闭原则)。
  4. 一致性:抽象工厂可保证产品族内的产品匹配(如苹果工厂只生产苹果生态产品)。

在实际开发中,工厂模式的思想广泛应用于框架(如 Spring 的 BeanFactory、Java 的 Calendar.getInstance()),是理解“依赖注入”“控制反转”等设计思想的基础。

spring中ioc容器是哪种工厂模式Spring 的 IoC 容器(控制反转容器)融合了多种工厂模式的思想,但其核心设计更接近 抽象工厂模式,同时也包含了简单工厂模式的特性,是一种“增强版”的工厂模式实现。

为什么说 IoC 容器接近抽象工厂模式?

抽象工厂模式的核心是“创建一系列相关或相互依赖的对象”,而 Spring IoC 容器的核心能力正是:

  1. 管理多种类型的 Bean(对象) 的创建(类似“产品族”);
  2. 通过统一的接口(如 BeanFactoryApplicationContext)提供对象的获取,隐藏具体创建细节。

具体对应关系如下:

  • 抽象工厂BeanFactory 接口(定义了获取 Bean 的标准方法,如 getBean());
  • 具体工厂ApplicationContext 的实现类(如 ClassPathXmlApplicationContextAnnotationConfigApplicationContext 等,负责实际创建和管理 Bean);
  • 抽象产品:各种 Bean 的接口或父类;
  • 具体产品:容器中管理的具体对象(如 UserServiceOrderDao 等)。

同时包含简单工厂模式的特性

Spring IoC 容器也具备简单工厂模式的特点:

  • 通过一个统一的入口(getBean() 方法) 创建不同类型的对象,客户端只需指定 Bean 的名称或类型(类似“参数”),无需关心具体创建逻辑;
  • 例如 context.getBean("userService")context.getBean(UserService.class),容器内部根据配置(XML/注解)动态创建对应的对象。

与传统工厂模式的区别

Spring IoC 容器并非严格遵循某一种经典工厂模式,而是进行了扩展:

  1. 动态配置:传统工厂模式的产品创建逻辑硬编码在工厂类中,而 Spring 通过配置文件(XML)或注解(@Component@Bean 等)动态定义 Bean 的创建规则,灵活性更高;
  2. 生命周期管理:IoC 容器不仅创建对象,还负责对象的初始化、依赖注入、销毁等全生命周期管理,这是传统工厂模式不具备的;
  3. 依赖注入(DI):容器会自动处理 Bean 之间的依赖关系(如 @Autowired),而传统工厂模式需要手动在工厂中管理依赖。

总结

Spring IoC 容器的设计思想以 抽象工厂模式 为基础(管理多种对象的创建,通过统一接口提供服务),同时吸收了简单工厂模式的便捷性(通过单一入口创建对象),并结合 IoC/DI 思想进行了增强,是一种更灵活、更强大的“超级工厂”实现。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐