工厂模式是创建型设计模式的核心代表,核心思想是将 “对象的创建逻辑” 与 “对象的使用逻辑” 分离,让调用者无需关心对象的具体创建细节,仅通过统一接口获取实例。它是大型项目(如 muduo 网络库)中解耦代码、提升扩展性的关键手段。
一、工厂模式的核心解决的问题
在未使用工厂模式时,调用者需要直接new具体类,会导致:
- 强耦合:调用者依赖具体类(如
EPollPoller),修改具体类需改动所有调用处;
- 创建逻辑分散:对象的创建条件(如 “系统是否支持 epoll”)散落在代码各处;
- 扩展性差:新增子类时,需修改所有
new的地方。
工厂模式通过 “工厂” 统一管理创建逻辑,彻底解决以上问题。
二、工厂模式的三大分类
根据复杂度和场景,工厂模式分为简单工厂、工厂方法、抽象工厂三类,适用场景逐步递进。
1. 简单工厂模式(Simple Factory)
这是最基础的工厂模式,通过一个工厂类 / 静态方法,根据条件创建不同子类实例。
核心结构
- 抽象产品:定义产品的统一接口(如
Poller);
- 具体产品:实现抽象产品的子类(如
EPollPoller、PollPoller);
- 工厂:提供静态方法,根据条件创建具体产品实例。
代码示例(以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
| class Poller { public: virtual void poll() = 0; };
class EPollPoller : public Poller { public: void poll() override { } };
class PollPoller : public Poller { public: void poll() override { } };
class PollerFactory { public: static Poller* createPoller() { if (::getenv("MUDUO_USE_POLL")) { return new PollPoller(); } else { return new EPollPoller(); } } };
|
调用方式
1 2 3
| 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
| class Poller { public: virtual void poll() = 0; };
class EPollPoller : public Poller { public: void poll() override { } };
class PollPoller : public Poller { public: void poll() override { } };
class PollerFactory { public: virtual Poller* createPoller() = 0; };
class EPollPollerFactory : public PollerFactory { public: Poller* createPoller() override { return new EPollPoller(); } };
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 风格的按钮 + 菜单”)时,抽象工厂模式通过一个工厂创建多个产品,保证产品族的一致性。
核心结构
- 抽象产品族:多个相关产品的抽象接口(如
Button、Menu);
- 具体产品族:同一风格的具体产品(如
WindowsButton、WindowsMenu);
- 抽象工厂:定义创建整个产品族的接口;
- 具体工厂:实现抽象工厂,创建对应风格的产品族。
代码示例(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
| class Button { public: virtual void render() = 0; };
class Menu { public: virtual void render() = 0; };
class WindowsButton : public Button { public: void render() override { } }; class WindowsMenu : public Menu { public: void render() override { } };
class MacButton : public Button { public: void render() override { } }; class MacMenu : public Menu { public: void render() override { } };
class UIFactory { public: virtual Button* createButton() = 0; virtual Menu* createMenu() = 0; };
class WindowsUIFactory : public UIFactory { public: Button* createButton() override { return new WindowsButton(); } Menu* createMenu() override { return new WindowsMenu(); } };
class MacUIFactory : public UIFactory { public: Button* createButton() override { return new MacButton(); } Menu* createMenu() override { return new MacMenu(); } };
|
调用方式
1 2 3 4 5 6 7
| UIFactory* factory = new WindowsUIFactory();
Button* btn = factory->createButton(); Menu* menu = factory->createMenu(); btn->render(); menu->render();
|
特点
- 优点:保证产品族的一致性(不会出现 “Windows 按钮 + Mac 菜单”);
- 缺点:扩展产品族困难(新增产品需修改抽象工厂),适合产品族固定的场景。
三、工厂模式的选型建议
| 场景 |
推荐模式 |
| 产品类型少,扩展频率低 |
简单工厂模式 |
| 产品类型多,需频繁扩展 |
工厂方法模式 |
| 需要创建关联的产品族 |
抽象工厂模式 |