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

一、工厂模式介绍

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

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

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

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

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

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


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

相关推荐
BD_Marathon几秒前
设计模式——里氏替换原则
java·设计模式·里氏替换原则
jmxwzy3 分钟前
设计模式总结
设计模式
J_liaty17 小时前
23种设计模式一代理模式
设计模式·代理模式
苏渡苇1 天前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式
短剑重铸之日1 天前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
feasibility.1 天前
AI 编程助手进阶指南:从 Claude Code 到 OpenCode 的工程化经验总结
人工智能·经验分享·设计模式·自动化·agi·skills·opencode
BD_Marathon1 天前
七大设计原则介绍
设计模式
YigAin1 天前
Unity23种设计模式之 享元模式
设计模式·享元模式
范纹杉想快点毕业2 天前
实战级ZYNQ中断状态机FIFO设计
java·开发语言·驱动开发·设计模式·架构·mfc
茂桑2 天前
DDD领域驱动设计-基础设施层
设计模式·架构