当前位置: 首页 > 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.dtcms.com/a/302611.html

相关文章:

  • 面向对象设计原则和设计模式分类
  • RTC时钟详解
  • 【智慧物联网平台】安装部署教程——仙盟创梦IDE
  • GitLab 公共仓库:coding 用到的 git 命令
  • PhpStorm + PHP8.1 + XDebug3 实现断点调试(亲测可用)
  • gitlab 在线合并分支a-分支b,解决冲突后,反向合并分支b-分支a
  • Vue 3 拖拽排序功能优化实现:从原理到实战应用
  • 8.1 ESP32CAM 服务器 网络摄像头
  • 本地大语言模型部署指南
  • TRIZ(5)——发明原理(3)
  • NVDB-CAVD 杯汽车信息安全系列赛事
  • 青少年编程中阶课
  • 【昆泰Chrontel CH7517A:DP转VGA】
  • Datawhale AI夏令营——列车信息智能问答——科大讯飞AI大赛(基于结构化数据的用户意图理解和知识问答挑战赛)
  • 在App Store Connect上编辑多个用户的访问权限
  • 医疗人工智能高质量数据集和语料库建设路径探析
  • 开始记录一步步学习pcl
  • Rust 最短路径、Tide、Partial、Yew、Leptos、数独实践案例
  • SpringCloud01——项目演变、微服务远程调用三种方式、springcloud介绍、nacos注册中心
  • 嵌入式开发学习———Linux环境下数据结构学习(四)
  • openlayer根据不同的状态显示不同的图层颜色
  • Java项目接口权限校验的灵活实现
  • AI学习之Cursor项目实战
  • ICPC 2024 网络赛(I)
  • 【大模型LLM】梯度累积(Gradient Accumulation)原理详解
  • linux I2C设备AW2013驱动示例
  • rhel网卡配置文件、网络常用命令、网卡名称优化和模拟不同网络区域通信
  • 服务器中的防火墙设置需要打开吗
  • 服务器查日志太慢,试试grep组合拳
  • 利用frp实现内网穿透功能(服务器)Linux、(内网)Windows