当前位置: 首页 > news >正文

C++项目 —— 基于多设计模式下的同步异步日志系统(5)(建造者模式)

C++项目 —— 基于多设计模式下的同步&异步日志系统(5)(建造者模式)

  • 一个问题
      • 建造者模式(Builder Pattern)
        • 主要概念
        • 适用场景
  • 代码实现

我们上次已经把日志器模块的主要的两大块已经编写的差不多了——同步日志器和异步日志器。如果有小伙伴对此还不太熟悉可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/147350462?spm=1011.2415.3001.5331

我们今天的题目建造者模式,是为了解决我们在简单测试的时候的一个问题:

一个问题

我们之前测试的时候,如果我们要构建一个日志器非常麻烦:

    logs::Formetter formatter("abc[%d{%H:%M:%S}][%c]%T%m%n");logs::Formetter::ptr fmt_ptr = std::make_shared<logs::Formetter>(formatter);auto st1 = logs::SinkFactory::create<logs::StdoutSink>();std::vector<logs::BaseSink::ptr> sinks = {st1};std::string logger_name = "asynclogger";logs::BaseLogger::ptr logger(new logs::AsyncLogger(logger_name, logs::Loglevel::value::DEBUG, fmt_ptr, sinks,logs::AsyncLooper::AsyncType::ASYNC_SAFE));logger->debug("main.cc", 53, "%s","格式化功能测试....");

构造一个日志器,我们就要用八九行代码,而且这是在我们很熟悉日志器结构的基础上我们才能写出来这样的代码,对于不熟悉代码结构的人,恐怕无法写出完整的代码来构建日志器。

因为日志器对象的构建过于复杂,所以我们就有了建造者模式的概念,大家可以点击以下连接来进行查看关于建造者模式的一些相关知识:

https://blog.csdn.net/qq_67693066/article/details/145543280?spm=1011.2415.3001.5331

建造者模式(Builder Pattern)

建造者模式是一种创建型设计模式,它允许逐步构建复杂的对象。这种模式对于需要构造具有许多可选组件的对象特别有用。通过使用建造者模式,可以避免构造函数参数列表过长的问题,并且使得代码更加清晰和易于维护。

主要概念
  1. 产品角色(Product):最终需要创建的复杂对象。
  2. 抽象建造者(Builder):定义创建产品各个部分的接口或抽象类。
  3. 具体建造者(Concrete Builder):实现抽象建造者的接口,负责构建产品的各个部分。
  4. 指挥者(Director):负责使用建造者来构建产品。它知道如何顺序调用建造步骤以正确地构造产品。
适用场景
  • 当对象需要很多参数来构造,特别是当有些参数是可选的时候。
  • 需要生成不同表示的产品时。
  • 构造过程必须允许被构造的不同对象独立变化。

代码实现

我们这里日志器对象的实现,刚好符合以上的条件,我们的思路是有一个基类的的建造者类,然后派生出不同职责的建造者

    //基类建造者class LoggerBuilder{public:LoggerBuilder():_logger_type(loggerType::LOGGER_SYNC),_looper_type(logs::AsyncLooper::AsyncType::ASYNC_SAFE),_limt_level(Loglevel::value::DEBUG){}//类型建造void buildLoggerType(loggerType type){_logger_type = type;}void buildEnableUnSafeAsync(){_looper_type = logs::AsyncLooper::AsyncType::ASYNC_UNSAFE;}void buildLoggerName(const std::string &name){_logger_name = name;}void buildLoggerlevel(Loglevel::value level){_limt_level = level;}void buildFormatter(const std::string &pattern){_formetter = std::make_shared<Formetter>(pattern);}//落地方向构造template<typename SinkType,typename... Args>void buildSink(Args &&...args){BaseSink::ptr psink = SinkFactory::create<SinkType>(std::forward<Args>(args)...);_sinks.push_back(psink);}virtual BaseLogger::ptr build() = 0;protected:logs::AsyncLooper::AsyncType _looper_type; //缓冲区类型loggerType _logger_type; //日志器类型std::string _logger_name; //日志器名称std::atomic<Loglevel::value> _limt_level; //日志输出等级logs::Formetter::ptr _formetter;std::vector<BaseSink::ptr> _sinks; //日志输出方向};

在这个基础上,我们派生出不同类型的建造者:

 //局部建造者class LocalLogger : public LoggerBuilder{public:BaseLogger::ptr build(){assert(_logger_name.empty() == false); //必须有日志器名称if(_formetter.get() == nullptr){_formetter = std::make_shared<Formetter>();}if (_sinks.empty()){buildSink<StdoutSink>();}if (_logger_type == loggerType::LOGGER_ASYNC){return std::make_shared<AsyncLogger>(_logger_name, _limt_level, _formetter, _sinks, _looper_type);}return std::make_shared<SyncLogger>(_logger_name, _limt_level, _formetter, _sinks);}};
}

我们可以来测试一下:

#include "utils.hpp"
#include "level.hpp"
#include "message.hpp"
#include "fometter.hpp"
#include "sink.hpp"
#include "logger.hpp"// 测试函数
void testLocalLogger() 
{// 创建局部建造者logs::LocalLogger local_logger;local_logger.buildLoggerName("synclogger");local_logger.buildLoggerlevel(logs::Loglevel::value::DEBUG);local_logger.buildFormatter("abc[%d{%H:%M:%S}][%c]%T%m%n");logs::BaseLogger::ptr logger = local_logger.build();logger->debug("main.cc", 53, "%s","格式化功能测试....");
}
int main()
{testLocalLogger() ;
}

在这里插入图片描述
这样大大简化了我们创建对象时的步骤,且不容易出错。

相关文章:

  • [操作系统] 信号
  • 2025.04.20
  • 代码随想录训练营第36天 ||1049. 最后一块石头的重量 II 494. 目标和 474. 一和零
  • 无回显RCE
  • 凤凰架构-数据管理与存储
  • 节点流和处理流基本使用
  • 探索 Model Context Protocol (MCP):它如何影响 AI 的表现?
  • Go语言--语法基础4--基本数据类型--浮点数类型
  • Cherry Studio配置MCP服务全流程解析
  • Unity3D仿星露谷物语开发37之浇水动画
  • 色谱图QCPColorMap
  • React Router V7使用详解
  • 用于手部康复设备的TinyML语音分类嵌入式人工智能模块
  • OpenCV 对图像进行阈值处理 cv2.threshold
  • 【Rust 精进之路之第11篇-借用·实践】切片 (Slices):安全、高效地引用集合的一部分
  • Opencv图像处理:轮廓检测、轮廓近似、绘制外接圆外接矩形
  • 嵌入式学习——opencv图像库编程
  • puzzle(0531)脑力航迹
  • 33-公交车司机管理系统
  • [ABAQUS有限元分析] 1.单个零件静力学分析
  • 瑞士成第15届北影节主宾国,6部佳作闪耀“瑞士电影周”
  • 钧正平发声:擅自更改地图标注,谷歌想当南海搅局者?!
  • 遇见古籍里的先贤,山西博物院“晋国垂棘”明日开展
  • 打捞一条文学传统的暗线
  • 神二十船箭组合体转运至发射区
  • 习近平会见马来西亚最高元首:开启中马关系新的“黄金50年”