多态性是构建可扩展日志系统的核心机制,它通过抽象formatter接口和sink接口实现格式化与分发解耦,支持运行时切换、单元测试、自定义扩展、多目标写入、层级嵌套、故障隔离及异步处理,并结合工厂模式与装饰器模式提升配置灵活性与线程安全性。

多态性是构建可扩展日志系统的核心机制,它让格式化逻辑与输出目标解耦,使日志组件既能统一处理消息,又能灵活适配不同输出方式(控制台、文件、网络等)和多样化格式(时间戳、线程ID、等级、上下文等)。
用抽象接口定义格式化行为
不硬编码每种格式的拼接逻辑,而是提取「格式化」这一共性能力为接口。例如定义 Formatter 抽象类或接口,声明 format(const LogMsg& msg) → std::string 方法。所有具体格式器(如 SimpleFormatter、JsonFormatter、ColorConsoleFormatter)都继承并实现它。这样,Logger 或 Sink 在调用时只依赖 Formatter 接口,无需关心具体格式如何生成。
- 支持运行时切换格式:只需替换 formatter 实例,无需修改日志记录或分发逻辑
- 便于单元测试:可用 MockFormatter 捕获格式化结果,验证字段是否按预期注入
- 兼容自定义需求:业务模块可提供专属 Formatter(如带 trace_id 的微服务格式)
用多态接收器实现日志分发
将“输出到哪里”抽象为 Sink 接口(如 write(const std::string& formatted)),不同目标对应不同子类:ConsoleSink、FileSink、TcpSink、UdpSink。分布式场景下,再引入 DistSink(分发接收器)——它本身也是 Sink,内部持有一组子 Sink,并在 write() 中遍历调用每个子 Sink 的 write 方法。
- 天然支持多目标写入:一条日志可同时落盘 + 推送远端 + 控制台打印
- 层级可嵌套:DistSink 的子 Sink 本身也可以是另一个 DistSink,形成树状分发拓扑
- 故障隔离:某个 Sink(如网络超时)异常不影响其他 Sink 正常工作
格式化与分发解耦,靠组合而非继承
Logger 不直接持有 ConsoleSink 或 FileSink,而是持有一个 Formatter 和一个 Sink(可以是单个,也可以是 DistSink)。日志流程变为:收集 → 格式化 → 分发。这三步之间仅通过接口通信,任意一环替换都不影响其余部分。
- 例如:将默认 SimpleFormatter 替换为 JsonFormatter,所有 Sink 自动获得 JSON 输出
- 又如:把本地 FileSink 换成 TcpSink,无需改动格式器或 Logger 接口
- 异步日志中,格式化可在主线程完成,序列化后的字符串交给后台线程分发,各环节仍保持多态契约
支持动态配置与策略注入
利用工厂模式配合多态,根据配置字符串(如 "json+tcp://10.0.1.5:514")创建对应的 Formatter 和 Sink 实例。配置解析器返回的是 Formatter* 和 Sink*,上层代码完全 unaware 具体类型。
- 配置驱动扩展:新增格式或输出方式,只需添加新类+注册工厂,不改核心流程
- 级别过滤可作为 Sink 的装饰器(Decorator 模式):WrapSink 调用前检查日志级别,符合才转发给内层 Sink
- 线程安全由具体 Sink 保证(如
ConsoleSink_mt、FileSink_mt),接口层不暴露并发细节











