工厂模式(Factory Pattern)

顾名思义,一个可以生产很多“类”的类(工厂)。

工厂模式几乎是所有面向对象开发中都会用到的一种设计模式,譬如Spring框架基于IoC(控制反转)容器的框架,大量依赖于工厂模式来管理对象的创建和生命周期。

工厂模式家族包含以下一些模式。

静态工厂模式(Static Factory Pattern)

一种简化版的工厂模式,通过包含静态方法的类来创建对象,客户端通过调用该静态方法并传入参数来获取所需的实例。

[] 静态工厂模式不是GoF的23中设计模式之一,但属于一种常见的编成实践。其核心是:

  • 提供一个静态工厂方法(static factory method)
  • 方法根据参数或逻辑返回不同的实现类实例
  • 客户端不需要使用new关键字直接创建对象

由于静态工厂模式不符合开闭原则,因此不能被继承,无法实现多态。往往只能用于创建单一固定类型的类,或者说是final的类,下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class SocketFactory {

public static ServerSocket createServerSocket() {
return new ServerSocket();
}

public static Socket createSocket() {
return new Socket();
}

public static Socket createSocket(boolean keepAlive) {
Socket socket = new Socket();
socket.setKeepAlive(keepAlive);
return socket;
}
...
}

基于它的定义,静态工厂更多的用作辅助类来使用,Java标准库中广泛使用了静态工厂方法,有:

  1. java.util.Collections#unmodifiableList(List<T> list)
  2. java.util.Arrays#asList(T... a)
  3. java.util.Optional#of(T value)
  4. java.time.LocalDate#now()
  5. java.nio.file.Paths.get(...)

静态工厂适用于框架内部本身希望统一对象的构建过程,同时不希望在外部进行扩展的类。

简单工厂模式(Simple Factory Pattern)

通过一个工厂类统一创建不同类型的对象,客户端无需指导具体类名,只需传入参数即可。

简单工厂也是违反了“开闭原则”,新增的产品类需要修改工厂类。

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
public interface Product {
void use();
}

public class ProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}

public class ProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}

public class SimpleFactory {

public Product createProduct(String type) { //
return switch(type) {
case "A" -> new ProductA();
case "B" -> new ProductB();
default -> throw new UnsupportedOperation("Unsupported Product Type");
}
}
}

违反“开闭原则”,每次新增产品时,都需要修改工厂类。

工厂方法模式(Factory Method Pattern)

每个工厂只生产一种产品,新增产品只需扩展不需要修改,符合开闭原则。

定义一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法模式把类的实例化过程推迟到子类。

对比UML可以发现,工厂方法就是在原来的简单工厂模式的前提下,将原来的SimpleFactory提升为interfaceabstract
,延迟到具体的工厂类进行构建。这种实现满足了“开闭原则”。

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
public interface Product {
void use();
}

public class ProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
public class ProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}

public interface Factory { //
Product createProduct();
}

public class FactoryA implement Factory {
public Product createProduct() {
return new ProductA();
}
}

public class FactoryB implement Factory {
public Product createProduct() {
return new ProductB();
}
}

工厂方法,由子类来决定类的实例化。

抽象工厂(Abstract Factory Pattern)

提供一个接口,用于创建一组相关的或依赖对象的家族,适用于多平台、多配置系统(如跨平台UI控件库)。

抽象工厂模式在基于原来的工厂方法模式的前提下,由单一类型,扩展为可以创建多种产品类型。

具体实现类,

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
48
49
50
public interface ProductA {
void featureA();
}
public class ProductA1 implement ProductA {
public void featureA() {
System.out.println("Feature of Product A1");
}
}
public class ProductA2 implement ProductA {
public void featureA() {
System.out.println("Feature of Product A2");
}
}
public interface ProductB {
void featureB();
}
public class ProductB1 implement ProductB {
public void featureB() {
System.out.println("Feature of Product B1");
}
}
public class ProductB2 implement ProductB {
public void featureB() {
System.out.println("Feature of Product B2");
}
}

public interface AbstractFactory { //
ProductA createProductA();
ProductB createProductB();
}

public class Factory1 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA1();
}
public ProductB createProductB() {
return new ProductB1();
}
}

public class Factory2 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA2();
}
public ProductB createProductB() {
return new ProductB2();
}
}

抽象工厂,由单一类型,扩展为支持多种类型。

总结

模式名称 创建对象数量 是否符合开闭原则 使用场景
简单工厂模式 单一类型 简单对象创建,不频繁变更
工厂方法模式 单一类型 需要灵活扩展产品类型
抽象工厂模式 多种类型 创建多个相关或依赖对象的家族