Java 工厂模式详解:从简单工厂到工厂方法

Java 工厂模式详解:从简单工厂到工厂方法

掌握对象创建的”封装”思想,是设计模式的第一道门

引言

工厂模式是 Java 后端面试出场率最高的设计模式之一。它的核心不是”造对象”,而是把创建对象的逻辑封装起来,让客户端只关心”用什么”不关心”怎么造”。

简单工厂和工厂方法名字像但本质不同——一个靠条件分支,一个靠多态。

1. 简单工厂:一个工厂搞定所有

结构

  • 抽象产品接口(Shape):定义公共方法
  • 具体产品类(CircleRectangleSquare):实现接口
  • 工厂类(ShapeFactory):根据参数决定创建哪种产品

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 1. 抽象产品接口
interface Shape {
void draw();
}

// 2. 具体产品类
class Circle implements Shape {
@Override
public void draw() {
System.out.println("画一个圆形");
}
}

class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("画一个矩形");
}
}

class Square implements Shape {
@Override
public void draw() {
System.out.println("画一个正方形");
}
}

// 3. 工厂类
class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) return null;
if (shapeType.equalsIgnoreCase("CIRCLE")) return new Circle();
if (shapeType.equalsIgnoreCase("RECTANGLE")) return new Rectangle();
if (shapeType.equalsIgnoreCase("SQUARE")) return new Square();
return null;
}
}

// 4. 客户端测试
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory factory = new ShapeFactory();
Shape shape1 = factory.getShape("CIRCLE"); shape1.draw();
Shape shape2 = factory.getShape("RECTANGLE"); shape2.draw();
Shape shape3 = factory.getShape("SQUARE"); shape3.draw();
}
}

运行结果

1
2
3
画一个圆形
画一个矩形
画一个正方形

2. 工作流程

  1. 客户端传入类型字符串(如 "CIRCLE"
  2. 工厂类根据字符串判断要造哪个对象
  3. 工厂内部 if-else 实例化对应产品
  4. 返回抽象产品引用(客户端只持有 Shape不知道具体是哪个类
  5. 客户端调用 draw() 完成业务

核心价值:客户端只依赖抽象产品和工厂,不依赖具体类。

3. 优缺点

优点

  • 解耦:客户端不接触 new Circle() 这类具体创建代码
  • 集中管理:所有创建逻辑在一个类里,方便排查

缺点(致命)

  • 违反开闭原则:新增产品必须修改 ShapeFactoryif-else
  • 工厂类膨胀:产品多了 if-else 臃肿难维护
  • 扩展性差:每次加产品都改老代码

4. 工厂方法:每个产品配独立工厂

简单工厂的问题:所有产品创建逻辑堆在一个类里。

工厂方法的解法为每种产品提供一个独立工厂子类

新增图形(如三角形)时:

  • 简单工厂:修改 ShapeFactory.getShapeif-else
  • 工厂方法:新增 TriangleFactory不修改任何已有代码

关键差异

维度 简单工厂 工厂方法
工厂类数量 1 个 每个产品一个
新增产品 改老代码 加新工厂类
开闭原则 违反 遵守
复杂度 略高
适用规模 产品少且稳定 产品会扩展

5. 实际应用场景

工厂模式在 JDK 源码里到处都是

  • Calendar.getInstance() ——根据 locale 返回不同日历实现
  • NumberFormat.getInstance() ——根据 locale 返回不同数字格式
  • Connection.getConnection() (JDBC) ——根据 URL 返回不同数据库连接

**这些都不是”简单工厂”**——它们都是工厂方法模式,因为产品族会扩展(新增数据库驱动、新增 locale)。

总结

工厂模式 = 封装对象创建

  • 简单工厂:一个工厂类 + if-else,适合产品少且稳定
  • 工厂方法:每个产品配独立工厂,遵守开闭原则,适合产品会扩展

面试回答模板

  1. 先讲简单工厂(入口简单)
  2. 点出简单工厂的缺点(违反开闭)
  3. 引出工厂方法的改进(多态代替条件分支)
  4. 举一个 JDK 实际例子(Calendar.getInstance()

下一步:用同样的”封装创建”思想学抽象工厂模式——处理”产品族”(如一整套 UI 组件:按钮+文本框+滚动条)。