深入解析 Delegate 模式:提升代码解耦性的最佳实践

Chrome内核中NET_EXPORT_PRIVATE Delegate 作用及实现方式解析(源码见附件)

HttpStreamFactory::Job 类中,Delegate 是一个抽象接口Delegate 类),用于处理 Job 执行过程中发生的各种事件,例如:

  • 连接成功,流已准备好。
  • 连接失败,发生错误。
  • 代理需要身份验证。
  • SSL 证书错误。

这个 Delegate 设计模式的核心思想是回调机制,让 Job 运行时能够异步通知外部调用方(通常是 HttpStreamFactory),从而解耦 Job 的执行逻辑和外部的控制逻辑。


1. NET_EXPORT_PRIVATE Delegate 的作用

NET_EXPORT_PRIVATE 是用于符号导出的宏,保证 Delegate 这个类在动态链接库(DLL)或者共享库中能够被外部使用。

class NET_EXPORT_PRIVATE Delegate { public: virtual void OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) = 0; virtual void OnBidirectionalStreamImplReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<BidirectionalStreamImpl> stream) = 0; virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<WebSocketHandshakeStream> stream) = 0; virtual void OnStreamFailed(int result, const NetErrorDetails& net_error_details, int resolve_error_info, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info) = 0; virtual void OnNeedsProxyAuth( const HttpResponseInfo& proxy_response, HttpAuthController* auth_controller) = 0; virtual void OnNeedsClientAuth(const SSLInfo& ssl_info) = 0; virtual void OnHttpsProxyTunnelResponseRedirect( const HttpResponseInfo& response_info, std::unique_ptr<HttpStream> stream) = 0; protected: virtual ~Delegate() = default; };

2. 设计思想

Delegate 采用的是回调接口模式(Callback Interface Pattern),即:

  1. Job 在执行过程中,遇到关键事件时,调用 Delegate 的方法,将事件通知给 HttpStreamFactory(或其他 Delegate 实现)。
  2. Job 本身不需要知道具体的处理逻辑,而是由 Delegate 实现类(通常是 HttpStreamFactoryImpl)决定如何处理这些事件。

这种设计模式的主要思想是解耦

  • Job 只负责建立 HTTP 连接,并通知 Delegate 结果,而不用关心调用方是谁或如何处理连接。
  • HttpStreamFactory 通过实现 Delegate,接收 Job 的事件,并采取相应的操作(如创建 HttpStream,处理认证,或者重试连接)。

3. 运行机制

整个流程如下:

  1. HttpStreamFactoryImpl 创建 Job 对象,并将自身作为 Delegate 传递:

    auto job = std::make_unique<HttpStreamFactory::Job>(/* 传递 this 作为 Delegate */);

  2. Job 运行过程中,遇到某些事件时,调用 Delegate 方法:

    delegate_->OnStreamReady(used_ssl_config, used_proxy_info, std::move(stream));

  3. HttpStreamFactoryImpl 作为 Delegate 实现类,定义如何处理这些回调:

    void HttpStreamFactoryImpl::OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) { // 处理已建立的流,例如通知请求者 }


4. Delegate 回调的具体情况

(1) 成功创建 HTTP 连接

  • Job 创建 HttpStream 后,调用:

    delegate_->OnStreamReady(used_ssl_config, used_proxy_info, std::move(stream));

  • HttpStreamFactoryImpl 处理此回调,向上层应用提供 HTTP 流。

(2) 连接失败

  • Job 连接失败时,调用:

    delegate_->OnStreamFailed(error_code, net_error_details, resolve_error_info, used_ssl_config, used_proxy_info);

  • HttpStreamFactoryImpl 处理失败情况,可能重试或通知应用层失败。

(3) 需要代理身份验证

  • 如果代理需要身份验证,Job 调用:

    delegate_->OnNeedsProxyAuth(proxy_response, auth_controller);

  • HttpStreamFactoryImpl 可能会请求用户输入凭据。

(4) 需要客户端证书

  • 若服务器要求客户端提供 SSL 证书,调用:

    delegate_->OnNeedsClientAuth(ssl_info);

  • HttpStreamFactoryImpl 处理客户端证书选择逻辑。

5. 这种实现方式的优点

1. 解耦(Decoupling):职责单一,代码更清晰

如果直接在 Job 里处理连接成功、失败、代理认证等逻辑,那么 Job 需要:

  • 负责连接建立。
  • 处理 HTTP/HTTPS/WebSocket 连接逻辑。
  • 处理代理认证。
  • 处理 SSL 证书问题。
  • 处理连接失败重试策略。

这样会导致 Job 变得复杂且难以维护
使用 Delegate 方式,把 Job 的职责限制在: ✅ 只负责执行网络连接任务,并通知 Delegate
❌ 不负责决定如何处理连接结果(这个交由 Delegate 处理)。


2. 代码可复用(Reusability):支持多种 Delegate 实现

Delegate 只是一组接口,可以有不同的实现,例如:

  • 标准 HTTP 连接HttpStreamFactoryImpl 实现 Delegate
  • WebSocket 连接WebSocketStreamFactory 也可以实现 Delegate
  • 双向流BidirectionalStreamFactory 也可以实现 Delegate

这样,同一个 Job 逻辑可以被不同类型的 Delegate 复用,而不需要为每种 HTTP 连接类型都重新写一套 Job 逻辑。

示例: 如果直接在 Job 里处理 WebSocket 连接,则:if (is_websocket) { // WebSocket 处理逻辑 } else { // 普通 HTTP 处理逻辑 }

这样 Job 代码会越来越复杂。使用 Delegate,不同类型的 Delegate 处理不同情况,Job 代码保持精简:delegate_->OnWebSocketHandshakeStreamReady(...);


3. 便于扩展(Extensibility):新增功能更简单

假设未来需要增加一个新的功能,比如HTTP/3 支持

  • 如果 Job 直接处理,就需要修改 Job 代码,增加大量 if-else 逻辑。
  • 如果使用 Delegate,只需要创建一个新的 Delegate 实现,比如 Http3StreamFactoryImpl,而不需要修改 Job

这样能避免修改已有代码,减少风险(符合**“开闭原则”**:对扩展开放,对修改封闭)。


4. 便于测试(Testability):可以Mock Delegate

在测试 Job 时,可以使用一个Mock Delegate,让 Job 只负责执行 HTTP 连接任务,而 Mock Delegate 负责检查回调是否正确触发。

示例:

class MockDelegate : public HttpStreamFactory::Job::Delegate { public: MOCK_METHOD(void, OnStreamReady, (const SSLConfig&, const ProxyInfo&, std::unique_ptr<HttpStream>), (override)); MOCK_METHOD(void, OnStreamFailed, (int, const NetErrorDetails&, int, const SSLConfig&, const ProxyInfo&), (override)); };

这样可以单独测试 Job 的逻辑,而不需要依赖 HttpStreamFactoryImpl,提高单元测试的独立性


5. 适用于异步回调(Asynchronous Callbacks)

网络请求通常是异步的(不会立即返回结果),而 Delegate 方式支持:

  • Job 运行时不需要等待,而是在连接完成后回调 Delegate
  • HttpStreamFactoryImpl 通过 Delegate 方式接收结果,而不影响 Job 的执行

这比直接在 Job 内部阻塞等待(同步处理)更高效,适用于大规模并发 HTTP 连接管理。


6. 支持多线程(Thread Safety)

如果 HttpStreamFactoryImpl 运行在不同的线程,使用 DelegateJob 运行在一个线程,而 HttpStreamFactoryImpl 运行在另一个线程,并通过异步回调传递数据,避免多线程竞争问题。

示例:

// Job 运行在 IO 线程 job->Start(); // 连接完成后,回调 Delegate,通知主线程 delegate_->OnStreamReady(...);

而如果直接在 Job 里处理,就需要额外的线程同步机制,增加代码复杂度。


结论

方式Delegate 方式直接在 Job 内部处理
耦合度(解耦 Job 和外部处理逻辑)Job 既负责连接,又处理各种事件)
代码复用(不同 Delegate 处理不同逻辑)(所有逻辑都写死在 Job 里)
扩展性(新增 Delegate 实现即可)(需要修改 Job 代码)
可测试性(可以 Mock Delegate 进行单测)(难以单独测试 Job
适用于异步(回调机制,适用于非阻塞 IO)(可能需要同步等待)
多线程支持(可以异步通知 Delegate 处理)(需要额外的线程同步机制)

综合来看,使用 Delegate 的方式更适合大规模、高并发、可扩展的 HTTP 连接管理,而直接在 Job 里处理虽然简单,但会导致代码复杂度增加、复用性降低,不适用于长期维护的项目。


6. 其他类似的设计模式

  1. 观察者模式(Observer Pattern)

    • 观察者监听 Job 状态变化,Job 在事件发生时通知所有观察者。
    • Delegate 方式可以看作一种简化的观察者模式。
  2. 策略模式(Strategy Pattern)

    • Delegate 也类似策略模式,Job 调用 Delegate 但不关心其具体实现,允许不同策略处理 HTTP 连接。

7. 总结

  • NET_EXPORT_PRIVATE Delegate 作用:
    提供 Job 事件通知机制,使 HttpStreamFactory 能异步处理流的创建、失败、认证等情况。
  • 实现方式:
    采用回调接口模式(Callback Interface Pattern),解耦 JobHttpStreamFactoryImpl
  • 核心机制:
    • Job 只负责连接建立,Delegate 负责处理业务逻辑。
    • 通过虚函数(纯虚方法 = 0),让 Job 仅需知道 Delegate 接口,而不关心具体实现。
    • 运行时,HttpStreamFactoryImpl 通过实现 Delegate 来处理 HTTP 连接结果。
  • 优点:
    • 解耦、低耦合、异步回调、提高代码复用性。
    • 适用于高并发 HTTP 连接管理。

这种模式是网络编程中非常常见的设计,可以适用于 HTTP 连接池、WebSocket 连接管理等场景。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值