知识模块
☕ Java 知识模块
十一、设计模式
工厂模式

工厂模式

工厂模式提供了一种创建对象的最佳方式,将对象的创建和使用分离。

一、三种工厂模式

简单工厂 ──→ 工厂方法 ──→ 抽象工厂
  (简单)       (中等)       (复杂)
模式特点适用场景
简单工厂一个工厂创建所有产品产品种类少且固定
工厂方法每个产品一个工厂产品种类可能增加
抽象工厂创建产品族多个产品族

二、简单工厂

1. 结构

┌─────────────┐     ┌─────────────┐
│   Product   │◄────│ ConcreteProduct │
│  (抽象产品)  │     │   (具体产品)     │
└─────────────┘     └─────────────┘

        │ 创建
┌───────┴───────┐
│ SimpleFactory │
│  (简单工厂)    │
└───────────────┘

2. 实现

// 抽象产品
public interface Product {
    void use();
}
 
// 具体产品A
public class ProductA implements Product {
    @Override
    public void use() {
        System.out.println("使用产品A");
    }
}
 
// 具体产品B
public class ProductB implements Product {
    @Override
    public void use() {
        System.out.println("使用产品B");
    }
}
 
// 简单工厂
public class SimpleFactory {
    public static Product create(String type) {
        switch (type) {
            case "A":
                return new ProductA();
            case "B":
                return new ProductB();
            default:
                throw new IllegalArgumentException("未知产品类型: " + type);
        }
    }
}
 
// 使用
Product product = SimpleFactory.create("A");
product.use();

3. 优缺点

优点

  • 客户端不需要知道具体产品类名
  • 集中管理对象创建

缺点

  • 违背开闭原则(新增产品需修改工厂)
  • 工厂类职责过重

三、工厂方法

1. 结构

┌─────────────┐     ┌─────────────┐
│   Product   │◄────│ ProductA    │
└─────────────┘     └─────────────┘
        ▲                 ▲
        │                 │ 创建
┌───────┴───────┐   ┌─────┴──────┐
│  Factory      │◄──│ FactoryA   │
│  (抽象工厂)    │   │ (具体工厂)  │
└───────────────┘   └────────────┘

2. 实现

// 抽象产品
public interface Product {
    void use();
}
 
// 具体产品
public class ProductA implements Product {
    @Override
    public void use() {
        System.out.println("使用产品A");
    }
}
 
public class ProductB implements Product {
    @Override
    public void use() {
        System.out.println("使用产品B");
    }
}
 
// 抽象工厂
public interface Factory {
    Product create();
}
 
// 具体工厂
public class FactoryA implements Factory {
    @Override
    public Product create() {
        return new ProductA();
    }
}
 
public class FactoryB implements Factory {
    @Override
    public Product create() {
        return new ProductB();
    }
}
 
// 使用
Factory factory = new FactoryA();
Product product = factory.create();
product.use();

3. 优缺点

优点

  • 符合开闭原则(新增产品只需新增工厂)
  • 符合单一职责原则
  • 客户端无需知道具体产品类

缺点

  • 类数量增加
  • 增加系统抽象性

四、抽象工厂

1. 结构

产品族:
┌──────────────┐  ┌──────────────┐
│  产品A系列    │  │  产品B系列    │
│ ┌──────────┐ │  │ ┌──────────┐ │
│ │ProductA1 │ │  │ │ProductB1 │ │
│ └──────────┘ │  │ └──────────┘ │
│ ┌──────────┐ │  │ ┌──────────┐ │
│ │ProductA2 │ │  │ │ProductB2 │ │
│ └──────────┘ │  │ └──────────┘ │
└──────────────┘  └──────────────┘
        ▲                 ▲
        │                 │
┌───────┴─────────────────┴───────┐
│        AbstractFactory          │
│  + createProduct1()             │
│  + createProduct2()             │
└─────────────────────────────────┘

2. 实现

// 抽象产品1
public interface Button {
    void click();
}
 
// 抽象产品2
public interface TextBox {
    void input();
}
 
// Windows 产品族
public class WindowsButton implements Button {
    @Override
    public void click() {
        System.out.println("Windows 按钮");
    }
}
 
public class WindowsTextBox implements TextBox {
    @Override
    public void input() {
        System.out.println("Windows 文本框");
    }
}
 
// Mac 产品族
public class MacButton implements Button {
    @Override
    public void click() {
        System.out.println("Mac 按钮");
    }
}
 
public class MacTextBox implements TextBox {
    @Override
    public void input() {
        System.out.println("Mac 文本框");
    }
}
 
// 抽象工厂
public interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}
 
// Windows 工厂
public class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }
    
    @Override
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }
}
 
// Mac 工厂
public class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }
    
    @Override
    public TextBox createTextBox() {
        return new MacTextBox();
    }
}
 
// 使用
GUIFactory factory;
if (System.getProperty("os.name").contains("Windows")) {
    factory = new WindowsFactory();
} else {
    factory = new MacFactory();
}
 
Button button = factory.createButton();
TextBox textBox = factory.createTextBox();

3. 优缺点

优点

  • 保证产品族的一致性
  • 符合开闭原则(新增产品族)
  • 客户端无需知道具体产品类

缺点

  • 新增产品类型困难(需修改所有工厂)
  • 增加系统复杂度

五、实际应用

1. JDK 中的应用

java.util.Calendar

Calendar cal = Calendar.getInstance();
// 根据时区和地区返回具体的 Calendar 实现

java.util.Collections

List<String> list = Collections.singletonList("hello");
// 工厂方法创建不可变集合

2. Spring 中的应用

BeanFactory

public interface BeanFactory {
    Object getBean(String name);
    <T> T getBean(Class<T> requiredType);
}

3. 日志框架

// SLF4J
Logger logger = LoggerFactory.getLogger(MyClass.class);
// 根据绑定返回具体的 Logger 实现(Logback/Log4j2)

六、模式对比

1. 简单工厂 vs 工厂方法

对比项简单工厂工厂方法
扩展性
类数量
复杂度
适用场景产品固定产品可扩展

2. 工厂方法 vs 抽象工厂

对比项工厂方法抽象工厂
产品维度单一产品产品族
扩展产品类型容易困难
扩展产品族困难容易
复杂度

七、面试高频问题

Q1: 工厂模式的核心思想是什么?

将对象的创建和使用分离,降低耦合度:

  • 客户端不直接 new 对象
  • 由工厂负责创建
  • 客户端只关心接口

Q2: 什么时候用简单工厂 vs 工厂方法?

产品种类少且固定 → 简单工厂
产品种类可能增加 → 工厂方法

Q3: 抽象工厂适合什么场景?

  • 需要创建产品族
  • 产品之间有关联关系
  • 需要保证产品族一致性

Q4: 工厂模式与建造者模式的区别?

模式关注点适用场景
工厂模式创建什么创建不同类型的对象
建造者模式怎么创建创建复杂对象,关注构建过程

Q5: Spring 的 BeanFactory 是什么模式?

BeanFactory 使用了工厂方法模式:

  • getBean() 方法创建 Bean
  • 不同的 ApplicationContext 是不同的工厂实现
  • 支持 Bean 的生命周期管理

八、最佳实践

1. 选择合适模式

// 产品固定,使用简单工厂
Product product = SimpleFactory.create("A");
 
// 产品可扩展,使用工厂方法
Factory factory = new FactoryA();
Product product = factory.create();
 
// 产品族,使用抽象工厂
GUIFactory factory = new WindowsFactory();
Button button = factory.createButton();
TextBox textBox = factory.createTextBox();

2. 配合配置使用

// 通过配置决定使用哪个工厂
String factoryType = config.get("factory.type");
Factory factory = FactoryProvider.getFactory(factoryType);

3. 使用反射减少类数量

public class ReflectionFactory {
    public static <T> T create(Class<T> clazz) {
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("创建实例失败", e);
        }
    }
}

更新时间:2026年3月16日