工厂模式是创建型设计模式的核心代表,核心思想是将 “对象的创建逻辑” 与 “对象的使用逻辑” 分离,让调用者无需关心对象的具体创建细节,仅通过统一接口获取实例。它是大型项目(如 muduo 网络库)中解耦代码、提升扩展性的关键手段。

一、工厂模式的核心解决的问题

在未使用工厂模式时,调用者需要直接new具体类,会导致:

  1. 强耦合:调用者依赖具体类(如EPollPoller),修改具体类需改动所有调用处;
  2. 创建逻辑分散:对象的创建条件(如 “系统是否支持 epoll”)散落在代码各处;
  3. 扩展性差:新增子类时,需修改所有new的地方。

工厂模式通过 “工厂” 统一管理创建逻辑,彻底解决以上问题。

二、工厂模式的三大分类

根据复杂度和场景,工厂模式分为简单工厂、工厂方法、抽象工厂三类,适用场景逐步递进。

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

这是最基础的工厂模式,通过一个工厂类 / 静态方法,根据条件创建不同子类实例。

核心结构
  • 抽象产品:定义产品的统一接口(如Poller);
  • 具体产品:实现抽象产品的子类(如EPollPollerPollPoller);
  • 工厂:提供静态方法,根据条件创建具体产品实例。
代码示例(以Poller为例)
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
// 抽象产品:Poller
class Poller {
public:
virtual void poll() = 0; // 统一接口
};

// 具体产品1:EPollPoller
class EPollPoller : public Poller {
public:
void poll() override { /* epoll实现 */ }
};

// 具体产品2:PollPoller
class PollPoller : public Poller {
public:
void poll() override { /* poll实现 */ }
};

// 简单工厂:静态方法创建实例
class PollerFactory {
public:
static Poller* createPoller() {
// 根据条件选择具体产品
if (::getenv("MUDUO_USE_POLL")) {
return new PollPoller();
} else {
return new EPollPoller();
}
}
};
调用方式
1
2
3
// 调用者仅依赖抽象Poller,不关心具体类
Poller* poller = PollerFactory::createPoller();
poller->poll();
特点
  • 优点:实现简单,集中管理创建逻辑;
  • 缺点:新增具体产品时需修改工厂(违反 “开闭原则”),适合产品类型较少的场景。

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

为解决简单工厂 “违反开闭原则” 的问题,工厂方法模式将工厂也抽象化:每个具体产品对应一个具体工厂,新增产品只需新增工厂,无需修改原有代码。

核心结构
  • 抽象产品:同简单工厂(如Poller);
  • 具体产品:同简单工厂(如EPollPoller);
  • 抽象工厂:定义创建产品的接口(如PollerFactory);
  • 具体工厂:实现抽象工厂,创建对应具体产品(如EPollPollerFactory)。
代码示例
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
// 抽象产品:Poller
class Poller {
public:
virtual void poll() = 0;
};

// 具体产品1:EPollPoller
class EPollPoller : public Poller {
public:
void poll() override { /* epoll实现 */ }
};

// 具体产品2:PollPoller
class PollPoller : public Poller {
public:
void poll() override { /* poll实现 */ }
};

// 抽象工厂:定义创建Poller的接口
class PollerFactory {
public:
virtual Poller* createPoller() = 0;
};

// 具体工厂1:创建EPollPoller
class EPollPollerFactory : public PollerFactory {
public:
Poller* createPoller() override {
return new EPollPoller();
}
};

// 具体工厂2:创建PollPoller
class PollPollerFactory : public PollerFactory {
public:
Poller* createPoller() override {
return new PollPoller();
}
};
调用方式
1
2
3
4
5
// 选择具体工厂(可通过配置/条件判断)
PollerFactory* factory = new EPollPollerFactory();
// 创建产品
Poller* poller = factory->createPoller();
poller->poll();
特点
  • 优点:完全符合 “开闭原则”,新增产品只需新增具体工厂;
  • 缺点:类数量爆炸(产品数 = 工厂数),适合产品类型较多且需频繁扩展的场景。

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

当需要创建一系列相互关联的产品族(如 “Windows 风格的按钮 + 菜单”“Mac 风格的按钮 + 菜单”)时,抽象工厂模式通过一个工厂创建多个产品,保证产品族的一致性。

核心结构
  • 抽象产品族:多个相关产品的抽象接口(如ButtonMenu);
  • 具体产品族:同一风格的具体产品(如WindowsButtonWindowsMenu);
  • 抽象工厂:定义创建整个产品族的接口;
  • 具体工厂:实现抽象工厂,创建对应风格的产品族。
代码示例(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
51
52
// 抽象产品1:Button
class Button {
public:
virtual void render() = 0;
};

// 抽象产品2:Menu
class Menu {
public:
virtual void render() = 0;
};

// 具体产品族1:Windows风格
class WindowsButton : public Button {
public:
void render() override { /* 渲染Windows按钮 */ }
};
class WindowsMenu : public Menu {
public:
void render() override { /* 渲染Windows菜单 */ }
};

// 具体产品族2:Mac风格
class MacButton : public Button {
public:
void render() override { /* 渲染Mac按钮 */ }
};
class MacMenu : public Menu {
public:
void render() override { /* 渲染Mac菜单 */ }
};

// 抽象工厂:定义创建产品族的接口
class UIFactory {
public:
virtual Button* createButton() = 0;
virtual Menu* createMenu() = 0;
};

// 具体工厂1:创建Windows产品族
class WindowsUIFactory : public UIFactory {
public:
Button* createButton() override { return new WindowsButton(); }
Menu* createMenu() override { return new WindowsMenu(); }
};

// 具体工厂2:创建Mac产品族
class MacUIFactory : public UIFactory {
public:
Button* createButton() override { return new MacButton(); }
Menu* createMenu() override { return new MacMenu(); }
};
调用方式
1
2
3
4
5
6
7
// 选择产品族(如Windows)
UIFactory* factory = new WindowsUIFactory();
// 创建同一风格的多个产品
Button* btn = factory->createButton();
Menu* menu = factory->createMenu();
btn->render();
menu->render();
特点
  • 优点:保证产品族的一致性(不会出现 “Windows 按钮 + Mac 菜单”);
  • 缺点:扩展产品族困难(新增产品需修改抽象工厂),适合产品族固定的场景。

三、工厂模式的选型建议

场景 推荐模式
产品类型少,扩展频率低 简单工厂模式
产品类型多,需频繁扩展 工厂方法模式
需要创建关联的产品族 抽象工厂模式