当前位置: 首页 > 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.lryc.cn/news/602323.html

相关文章:

  • 记一次IDEA启动微服务卡住导致内存溢出问题
  • Java设计模式之<建造者模式>
  • idea编译报错 java: 非法字符: ‘\ufeff‘ 解决方案
  • 解决windows系统下 idea、CLion 控制台中文乱码问题
  • 机器学习sklearn:不纯度与决策树构建
  • Rust实战:AI与机器学习自动炒饭机器学习
  • Linux系统Centos7 安装mysql5.7教程 和mysql的简单指令
  • 搭建HAProxy高可用负载均衡系统
  • 【拓扑排序 缩点】P2272 [ZJOI2007] 最大半连通子图|省选-
  • Linux应用开发基础知识——LInux学习FreeType编程(七)
  • 【C++进阶】---- 二叉搜索树
  • 基于LangGraph Cli的智能数据分析助手
  • Android中PID与UID的区别和联系(2)
  • Go 语言面试题
  • 数据分析干货| 衡石科技可视化创作之仪表盘控件如何设置
  • GitLab 公共仓库:coding 用到的 git 命令
  • Springboot社区养老保险系统小程序
  • 一文理清 Linux 软件管理核心知识:从程序组成到包管理工具
  • Java面试宝典:MySQL8新特性
  • shell学习从入门到精通(第二部分)
  • 机器学习sklearn:决策树的参数、属性、接口
  • nccl中__syncthreads的作用及例子 (来自deepseek)
  • 135端口与WMI攻防全解析
  • 网络安全基础知识【4】
  • python中类变量 __slots__ 解析
  • 5190 - 提高:DFS序和欧拉序:树上操作(区域修改1)
  • 排序算法 (Sorting Algorithms)-JS示例
  • AI原生应用:从人机关系重构到数字空间革命
  • RF随机森林分类预测+特征贡献SHAP分析,通过特征贡献分析增强模型透明度,Matlab代码实现,引入SHAP方法打破黑箱限制,提供全局及局部双重解释视角
  • 力扣7:整数反转