设计模式(二):工厂模式

一、工厂模式介绍

工厂模式本质是将对象创建与使用 解耦,避免业务代码直接依赖具体实现。 根据系统复杂度和变化维度不同,常见有简单工厂、工厂方法和抽象工厂三种形式。

第一,简单工厂。 简单工厂通过一个工厂类,根据参数决定创建哪一种具体对象。 它的优点是实现简单、集中管理对象创建 ,但缺点是新增类型需要修改工厂代码,不符合 开闭原则,更适合类型稳定、变化不频繁的场景。

第二, 工厂方法 工厂方法将"创建哪个对象"延迟到子类中完成,每一种产品对应一个具体工厂,通过多态替代条件分支。 它解决了简单工厂扩展性差的问题,符合 开闭原则,适用于"创建流程一致,但具体类型会不断扩展"的场景。

第三,抽象工厂。 抽象工厂用于创建一整套相互关联的对象 ,强调产品族的概念,比如同一套环境下的多个组件必须保持一致。 它的优势是保证产品族一致性,但代价是结构复杂,新增产品类型需要修改所有具体工厂,适合系统初始化阶段做整体选型的场景。

总结来说: 简单工厂关注"创建哪一个对象", 工厂方法关注"如何扩展对象创建", 抽象工厂关注"如何创建一整套相关对象"。 三者没有优劣之分,只有是否匹配当前系统复杂度和变化维度

二、示例:网络服务器中的「连接对象创建」(muduo / reactor 场景)

背景

在一个基于 Reactor 的网络服务器中(比如 muduo):

  • 新连接到来时

  • 都需要创建一个 Connection 对象

  • 创建流程是固定的

比如:

  1. 分配 fd

  2. 设置 socket 选项

  3. 注册到 EventLoop

  4. 绑定回调

  5. 放入连接管理器

但是:

不同业务的连接行为不同:

  • HTTP 连接

  • WebSocket 连接

  • RPC 连接

  • 内部控制连接


如果不用工厂方法,会发生什么?

❌ 典型写法

cpp 复制代码
void Server::onNewConnection(int fd) {
    if (type == HTTP) { 
        conn = new HttpConnection(fd); 
    } 
    else if (type == WS) { 
        conn = new WebSocketConnection(fd); 
    }
    else if (type == RPC) { conn = new RpcConnection(fd); 
    } 
}

工程问题(你可以直接说):

  • Server 强依赖所有具体连接类型

  • 每加一种连接,必须修改核心 IO 代码

  • 违反开闭原则

  • 测试和扩展都困难


工厂方法怎么解这个问题?

抽象一个"连接工厂"

cpp 复制代码
class ConnectionFactory {
public:
     virtual ~ConnectionFactory() = default;
     virtual std::unique_ptr<Connection> create(int fd) = 0;
};

每种协议一个工厂(重点)

cpp 复制代码
class HttpConnectionFactory : public ConnectionFactory {
public:std::unique_ptr<Connection> create(int fd) override {auto conn = std::make_unique<HttpConnection>(fd);
        conn->initHttpContext();return conn;
    }
};
class RpcConnectionFactory : public ConnectionFactory {
public:std::unique_ptr<Connection> create(int fd) override {auto conn = std::make_unique<RpcConnection>(fd);
        conn->initCodec();return conn;
    }
};

Server 层发生了什么变化?

cpp 复制代码
void Server::onNewConnection(int fd) {
    auto conn = factory_->create(fd);
    connectionManager_.add(std::move(conn));
}

🔥 关键点:

Server 不再关心"创建哪种连接", 只负责统一的创建流程和生命周期管理


这为什么是「必须用工厂方法」?

这里必须用工厂方法,而不是简单工厂,是因为连接类型会持续扩展,而 Server 是稳定核心模块,不能频繁修改。

Q:为什么不用简单工厂?

答:

因为连接类型是开放变化的,如果用简单工厂,每加一种协议都要改工厂逻辑,本质还是 if-else 膨胀。

Q:那抽象工厂呢?

答:

抽象工厂更适合一次性创建一整套组件,比如 Connection + Codec + Dispatcher。 这里只是单一对象创建,工厂方法更合适。


总结

在网络服务器中,新连接的创建流程是固定的,但具体连接类型会不断扩展,比如 HTTP、RPC、WebSocket。 如果在 Server 中直接 if-else 创建,会导致核心 IO 代码频繁修改。 我通过工厂方法,把连接创建延迟到具体工厂中,用多态替代条件分支,保证 Server 对扩展开放、对修改关闭。


本篇文章讨论了工厂模式,欢迎评论!

相关推荐
范纹杉想快点毕业18 小时前
实战级ZYNQ中断状态机FIFO设计
java·开发语言·驱动开发·设计模式·架构·mfc
茂桑1 天前
DDD领域驱动设计-基础设施层
设计模式·架构
小温冲冲1 天前
通俗且全面精讲工厂设计模式
设计模式
进击的小头1 天前
设计模式与C语言高级特性的结合
c语言·设计模式
小温冲冲1 天前
通俗且全面精讲单例设计模式
开发语言·javascript·设计模式
Vivienne_ChenW1 天前
DDD领域模型在项目中的实战
java·开发语言·后端·设计模式
sg_knight1 天前
原型模式(Prototype)
python·设计模式·开发·原型模式
短剑重铸之日1 天前
《设计模式》第九篇:三大类型之结构型模式
java·后端·设计模式·组合模式·代理模式·结构性模式
忧郁的Mr.Li1 天前
设计模式--单例模式
javascript·单例模式·设计模式
范纹杉想快点毕业1 天前
状态机设计模式与嵌入式系统开发完整指南
java·开发语言·网络·数据库·mongodb·设计模式·架构