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

结合项目阐述 设计模式:单例、工厂、观察者、代理

原文链接:https://download.csdn.net/blog/column/12433305/133862792#_1613

1、工厂模式应用

C++17及之后可编译

/*日志落地模块的实现1.抽象落地基类2.派生子类(根据不同落地方向进行派生)3.使用工厂模式进行创建与表示的分离
*/#ifndef __M_SINK_H__
#define __M_SINK_H__//#include "util.hpp"
#include <memory>
#include <fstream>
#include <sstream>
#include <cassert>#include <filesystem>
#include <iostream>namespace lgrlog
{class LogSink{public://ptr有什么用?//ptr是一个智能指针,可以自动管理对象生命周期,不需要手动释放//ptr是一个父类指针,可以指向子类对象,但是不能调用子类独有接口,只能调用父类接口,所以这里创建的是LogSink的智能指针using ptr = std::shared_ptr<LogSink>;// 定义智能指针类型(用强指针类型)// 日志落地接口LogSink() {}virtual ~LogSink() {}virtual void log(const char* data, size_t len) = 0;};// 落地方向类型1:标准输出(控制台)class StdoutSink : public LogSink{public:// 将日志写入到标准输出void log(const char* data, size_t len) override{std::cout.write(data, len);}};// 落地方向类型2:指定文件class FileSink : public LogSink{public:// 构造时传入文件名,并打开文件,将操作句柄管理起来FileSink(const std::string& pathname) :_pathname(pathname){// 1.创建日志文件所在的目录//util::File::createDirectory(util::File::path(pathname));//util::File::createDirectory(util::File::path(pathname));std::filesystem::path path(pathname);if (!std::filesystem::exists(path.parent_path())){std::filesystem::create_directories(path.parent_path());}// 2.创建并打开日志文件_ofs.open(_pathname, std::ios::binary | std::ios::app);assert(_ofs.is_open());}// 将日志写入到指定文件void log(const char* data, size_t len) override{_ofs.write(data, len);assert(_ofs.good());}private:std::string _pathname;std::ofstream _ofs;};// 落地方向类型3:滚动文件(以大小进行滚动)class RollBySizeSink : public LogSink{public:// 构造时传入文件名,并打开文件,将操作句柄管理起来RollBySizeSink(const std::string& basename, size_t max_size):_basename(basename), _max_fsize(max_size), _cur_fsize(0), _name_count(0){std::string pathname = createNewFile();// 1.创建日志文件所在的目录//util::File::createDirectory(util::File::path(pathname));std::filesystem::path path(pathname);if (!std::filesystem::exists(path.parent_path())){std::filesystem::create_directories(path.parent_path());}// 2.创建并打开日志文件_ofs.open(pathname, std::ios::binary | std::ios::app);assert(_ofs.is_open());}// 将日志写入到标准输出--写入时判断文件大小,超过最大大小就要切换文件void log(const char* data, size_t len) override{if (_cur_fsize >= _max_fsize){_ofs.close();std::string pathname = createNewFile();_ofs.open(pathname, std::ios::binary | std::ios::app);assert(_ofs.is_open());_cur_fsize = 0;}_ofs.write(data, len);assert(_ofs.good());_cur_fsize += len;}private:// 进行大小判断,超过指定大小则创建新文件std::string createNewFile(){// 获取系统时间,以时间构造文件扩展名//time_t t = util::Date::now();//struct tm lt;//localtime_r(&t, &lt);std::stringstream filename;filename << _basename;/*filename << lt.tm_year + 1900;filename << lt.tm_mon + 1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;*/filename << "-";filename << _name_count++;filename << ".log";return filename.str();}private:// 通过基础文件名 + 扩展文件名(以时间生成)组成一个实际的当前输出文件名size_t _name_count;std::string _basename;  // ./log/base-      ->      ./log/base-20250114110125.logstd::ofstream _ofs;size_t _max_fsize;   // 记录最大大小,当前文件超过这个大小就要切换文件size_t _cur_fsize;   // 记录当前文件已经写入的数据大小};class SinkFactory{public://SinkType: 落地方向 类型(继承自LogSink的3个派生类之一)//Args...: 构造函数参数类型template<typename SinkType, typename ...Args>static LogSink::ptr create(Args&& ...args)// 这里的Args...表示参数包,可以传入多个参数{//模式:工厂模式// 1.创建对象// 2.返回对象// 3.对象管理由工厂负责,不由调用者管理// 4.对象创建与表示分离  return std::make_shared<SinkType>(std::forward<Args>(args)...);}};
}int main()
{// 1.1创建落地对象 //ptr是一个智能指针,可以自动管理对象生命周期,不需要手动释放//ptr是一个父类指针,可以指向子类对象,但是不能调用子类独有接口,只能调用父类接口,所以这里创建的是LogSink的智能指针lgrlog::LogSink::ptr sink = lgrlog::SinkFactory::create<lgrlog::StdoutSink>();// 1.2落地日志sink->log("hello world", 11);// 落地方向类型1:log标准输出// 2.1 创建另一个落地对象std::string filename = "./log/test.log";lgrlog::LogSink::ptr sink2 = lgrlog::SinkFactory::create<lgrlog::FileSink>(filename);// 2.2 落地日志sink2->log("hello world", 11);// 落地方向类型2:log指定到文件// 3.1 创建另一个落地对象lgrlog::LogSink::ptr sink3 = lgrlog::SinkFactory::create<lgrlog::RollBySizeSink>("./log/roll-by-size", 1024 * 1024);// 3.2 落地日志sink3->log("hello world", 11);// 落地方向类型3:滚动显示logreturn 0;
}#endif

2、

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

相关文章:

  • OSPF笔记
  • 图片上传 el+node后端+数据库
  • 4.应用层自定义协议与序列化
  • 生物信息学数据技能-学习系列001
  • 深入Go并发编程:Channel、Goroutine与Select的协同艺术
  • Deepseek + browser-use 轻松实现浏览器自动化
  • MCP error -32000: Connection closed
  • c++: 尾置返回类型(Trailing Return Type)
  • GaussDB 查看会话连接数
  • Android通知(Notification)全面解析:从基础到高级应用
  • React Immer 不可变数据结构的处理
  • 05 OpenCV--图像预处理之图像轮廓、直方图均衡化、模板匹配、霍夫变化、图像亮度变化、形态学变化
  • 暴雨服务器更懂人工智能+
  • JVM 笔记:类加载、内存管理、垃圾收集与垃圾收集器
  • 婚纱摄影管理系统(发送邮箱、腾讯地图API、物流API、webSocket实时聊天、协同过滤算法、Echarts图形化分析)
  • cacti的RCE
  • Mysql表的增删改查(进阶)
  • 解析分区、挂载与块设备:Linux 存储管理核心命令详解
  • 二级域名分发源码最新开源版
  • 基于Flask的智能停车场管理系统开发实践
  • 【Linux】重生之从零开始学习运维之mysql用户管理
  • 天学网面试 —— 中级前端开发岗位
  • 网易易盾、腾讯ACE等主流10款游戏反外挂系统对比
  • DDD之整体设计流程(2)
  • Pandas 里的分箱操作
  • Mybatis_4
  • Effective C++ 条款07:为多态基类声明virtual析构函数
  • 【esp32s3】7 - VSCode + PlatformIO + Arduino + 构建项目
  • 前端高级综合搜索组件 SearchBox 使用详解!
  • 学习dify:一个开源的 LLM 应用开发平台