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

一、工厂模式介绍

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

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

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

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

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

二、示例:网络服务器中的「连接对象创建」(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 对扩展开放、对修改关闭。


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

相关推荐
前端小臻2 小时前
软件的设计模式
设计模式
休息一下接着来4 小时前
C++ 设计模式:Pimpl(Pointer to Implementation)
c++·算法·设计模式
小码过河.4 小时前
设计模式——原型模式
设计模式·原型模式
进击的小头5 小时前
为什么C语言也需要设计模式
c语言·开发语言·设计模式
小码过河.7 小时前
设计模式——外观模式
设计模式·外观模式
ipod7418 小时前
#设计模式
设计模式
小码过河.8 小时前
设计模式——命令模式
设计模式·命令模式
小码过河.8 小时前
设计模式——备忘录模式
设计模式·备忘录模式
代码or搬砖8 小时前
设计模式之单例模式
单例模式·设计模式