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

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() ;
}

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

http://www.xdnf.cn/news/624.html

相关文章:

  • 【条形码识别改名工具】如何批量识别图片条形码,并以条码内容批量重命名,基于WPF和Zxing的开发总结
  • Spring之我见 - Spring Boot Starter 自动装配原理
  • 数字图像处理知识点小记1
  • 【Oracle专栏】删除用户 释放表空间
  • 注意力机制(np计算示例)单头和多头
  • 2025.4.14-2025.4.20学习周报
  • UCSC CTF 2025|MISC
  • (学习总结34)Linux 库制作与原理
  • Python Web开发常用框架介绍
  • SSM--AOP 日志
  • maven的安装与配置、IDEA集成maven
  • Redis 事件循环(Event Loop)
  • 主机运行状态的监控命令(top命令)
  • python——字典
  • Opencv图像处理:模板匹配对象
  • Python小游戏:俄罗斯方块简易版三
  • skywalking agent 关联docker镜像
  • 关于AI:记忆、身份和锁死
  • 【MySQL】MySQL的基础语法及其语句的介绍
  • Qt6离线安装过程
  • 在win上安装Ubuntu安装Anaconda(linx环境)
  • React 自定义Hook之usePrevious
  • CFS 的调度类型:普通调度 vs 组调度
  • 【中级软件设计师】语言处理程序(汇编程序、解释程序、编译程序)附软考真题
  • go语言优雅关机和优雅重启笔记
  • WEMOS LOLIN32
  • 第一部分笔试Day_01到Day24_每天两道OJ
  • 图解MCP:Model Context Protocol
  • 从零开始用Pytorch实现LLaMA 4的混合专家(MoE)模型
  • 【Java】接口interface学习