C++ 设计模式实战:工厂模式与单例模式深度应用
C++ 设计模式实战聚焦工厂模式与单例模式。内容涵盖简单工厂、工厂方法、抽象工厂三种层次,以及饿汉式、懒汉式单例实现。通过计算器、日志系统、跨平台 UI 等案例,演示对象创建分离、全局唯一实例管理及线程安全优化。总结核心原则、优缺点、常见陷阱及实战技巧,助力编写高内聚低耦合的 C++ 代码。

C++ 设计模式实战聚焦工厂模式与单例模式。内容涵盖简单工厂、工厂方法、抽象工厂三种层次,以及饿汉式、懒汉式单例实现。通过计算器、日志系统、跨平台 UI 等案例,演示对象创建分离、全局唯一实例管理及线程安全优化。总结核心原则、优缺点、常见陷阱及实战技巧,助力编写高内聚低耦合的 C++ 代码。

重点: 工厂模式的层次演进逻辑、单例模式的线程安全实现、设计模式在项目中的落地技巧
在 C++ 开发中,'设计模式'是前人总结的代码设计经验模板,用于解决特定场景下的代码复用、扩展性、维护性问题。设计模式不直接提供可运行的代码,而是提供一套抽象的设计思路,帮助我们编写'高内聚、低耦合'的优质代码。
实际开发中,我们常遇到以下问题:
if-else 判断);设计模式通过标准化的设计思路,将'变化的部分'与'不变的部分'分离,例如工厂模式负责统一管理对象创建,单例模式确保全局唯一实例,从而解决上述问题。
在学习具体模式前,需牢记以下核心原则(为后续模式应用奠定基础):
工厂模式是创建型设计模式的核心,其核心思想是'将对象的创建与使用分离',由专门的工厂类负责对象创建,使用者无需关心对象的创建细节(如构造函数参数、初始化流程)。
根据复杂度和扩展性,工厂模式分为三个层次:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式(Simple Factory):定义一个工厂类,根据传入的参数,动态创建不同产品类的实例(所有产品都继承自同一个抽象基类)。
假设我们需要开发一个简单计算器,支持加法、减法、乘法、除法运算。若直接在主函数中创建运算对象,会导致 if-else 冗余且扩展性差,使用简单工厂模式可解决该问题。
首先定义所有运算的抽象基类 Operation,声明统一的接口 GetResult():
#include <iostream>
#include <string>
using namespace std;
// 产品抽象基类:运算
class Operation {
public:
double numA; // 运算数 A
double numB; // 运算数 B
// 纯虚函数:计算结果(子类必须实现)
virtual double GetResult() const = 0;
// 虚析构函数:确保子类析构时正确释放资源
virtual ~Operation() {}
};
为每种运算实现具体产品类,继承自 Operation 并实现 GetResult():
// 具体产品:加法运算
class OperationAdd : public Operation {
public:
double GetResult() const override {
return numA + numB;
}
};
// 具体产品:减法运算
class OperationSub : public Operation {
public:
double GetResult() const override {
return numA - numB;
}
};
// 具体产品:乘法运算
class OperationMul : public Operation {
public:
double GetResult() const override {
return numA * numB;
}
};
// 具体产品:除法运算(增加除数不为 0 的校验)
class OperationDiv : public Operation {
public:
double GetResult() const override {
if (numB == 0) {
throw runtime_error("除数不能为 0!");
}
return numA / numB;
}
};
创建工厂类 OperationFactory,提供静态方法 CreateOperation(),根据传入的运算符参数创建对应的运算对象:
// 简单工厂类:负责创建运算对象
class OperationFactory {
public:
// 静态方法:根据运算符创建对应的运算对象
static Operation* CreateOperation(char op) {
Operation* operation = nullptr;
switch (op) {
case '+': operation = new OperationAdd(); break;
case '-': operation = new OperationSub(); break;
case '*': operation = new OperationMul(); break;
case '/': operation = new OperationDiv(); break;
default: throw invalid_argument("不支持的运算符!");
}
return operation;
}
};
客户端只需调用工厂类的静态方法,传入参数即可获取对象,无需关心对象创建细节:
int main() {
try {
// 1. 通过工厂创建加法对象
Operation* addOp = OperationFactory::CreateOperation('+');
addOp->numA = 10;
addOp->numB = 20;
cout << "10 + 20 = " << addOp->GetResult() << endl; // 输出:30
delete addOp; // 释放资源
// 2. 通过工厂创建除法对象
Operation* divOp = OperationFactory::CreateOperation('/');
divOp->numA = 50;
divOp->numB = 5;
cout << "50 / 5 = " << divOp->GetResult() << endl; // 输出:10
delete divOp;
// 3. 测试除数为 0 的异常
Operation* errDivOp = OperationFactory::CreateOperation('/');
errDivOp->numA = 30;
errDivOp->numB = 0;
cout << "30 / 0 = " << errDivOp->GetResult() << endl;
delete errDivOp;
} catch (const exception& e) {
cout << "错误:" << e.what() << endl; // 输出:除数不能为 0!
}
return 0;
}
✅ 优点:
⚠️ 缺点:
switch 逻辑;switch 会非常长)。工厂方法模式(Factory Method):定义一个创建对象的接口(抽象工厂),让子类决定实例化哪个产品类。即'将工厂的创建逻辑延迟到子类',每个产品对应一个专属工厂。
假设我们需要开发一个日志系统,支持文件日志(写入文件)、控制台日志(打印到控制台)、数据库日志(存入数据库),且未来可能新增'网络日志'。使用工厂方法模式,可实现无侵入式扩展。
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
// 产品抽象基类:日志器
class Logger {
public:
// 纯虚函数:写入日志
virtual void WriteLog(const string& message) = 0;
virtual ~Logger() {}
};
// 具体产品 1:控制台日志
class ConsoleLogger : public Logger {
public:
void WriteLog(const string& message) override {
cout << "[控制台日志] " << message << endl;
}
};
// 具体产品 2:文件日志(写入 log.txt)
class FileLogger : public Logger {
public:
void WriteLog(const string& message) override {
ofstream logFile("log.txt", ios::app); // 追加模式写入文件
if (logFile.is_open()) {
logFile << "[文件日志] " << message << endl;
logFile.close();
} else {
throw runtime_error("无法打开日志文件!");
}
}
};
// 具体产品 3:数据库日志(模拟写入数据库)
class DatabaseLogger : public Logger {
public:
void WriteLog(const string& message) override {
// 模拟数据库连接与写入
cout << "[数据库日志] 连接数据库成功,写入日志:" << message << endl;
}
};
抽象工厂类声明创建产品的纯虚方法,由子类实现:
// 抽象工厂基类:日志工厂
class LoggerFactory {
public:
// 纯虚函数:创建日志器对象
virtual Logger* CreateLogger() = 0;
virtual ~LoggerFactory() {}
};
每个产品对应一个专属工厂,实现 CreateLogger() 方法:
// 具体工厂 1:控制台日志工厂
class ConsoleLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override {
return new ConsoleLogger();
}
};
// 具体工厂 2:文件日志工厂
class FileLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override {
return new FileLogger();
}
};
// 具体工厂 3:数据库日志工厂
class DatabaseLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override {
return new DatabaseLogger();
}
};
客户端根据需求选择对应的工厂,再通过工厂创建产品:
int main() {
try {
// 1. 使用控制台日志
LoggerFactory* consoleFactory = new ConsoleLoggerFactory();
Logger* consoleLogger = consoleFactory->CreateLogger();
consoleLogger->WriteLog("用户登录成功"); // 输出:[控制台日志] 用户登录成功
delete consoleLogger;
delete consoleFactory;
// 2. 使用文件日志(会生成 log.txt 文件)
LoggerFactory* fileFactory = new FileLoggerFactory();
Logger* fileLogger = fileFactory->CreateLogger();
fileLogger->WriteLog("系统启动完成"); // 写入 log.txt
delete fileLogger;
delete fileFactory;
// 3. 使用数据库日志
LoggerFactory* dbFactory = new DatabaseLoggerFactory();
Logger* dbLogger = dbFactory->CreateLogger();
dbLogger->WriteLog("数据备份成功"); // 输出:[数据库日志] 连接数据库成功...
delete dbLogger;
delete dbFactory;
// 【扩展】新增网络日志时,只需添加 NetworkLogger 和 NetworkLoggerFactory,无需修改现有代码
} catch (const exception& e) {
cout << "日志写入失败:" << e.what() << endl;
}
return 0;
}
✅ 优点:
⚠️ 缺点:
ConsoleLoggerFactory),增加了客户端的学习成本。抽象工厂模式(Abstract Factory):提供一个接口,用于创建一系列相关或相互依赖的对象(产品族),而无需指定它们的具体类。
简单来说,工厂方法模式解决'同一产品等级结构'的扩展问题,抽象工厂模式解决'同一产品族'的创建问题。
假设我们需要开发一个跨平台 UI 库,支持 Windows 和 Mac 两个平台,每个平台包含'按钮(Button)'和'文本框(TextBox)'两个组件(即两个产品族:Windows 产品族、Mac 产品族)。
#include <iostream>
#include <string>
using namespace std;
// 产品等级 1:按钮
class Button {
public:
virtual void Display() = 0; // 显示按钮
virtual ~Button() {}
};
// 产品等级 2:文本框
class TextBox {
public:
virtual void Display() = 0; // 显示文本框
virtual ~TextBox() {}
};
// Windows 产品族
class WindowsButton : public Button {
public:
void Display() override {
cout << "显示 Windows 风格按钮(蓝色、矩形)" << endl;
}
};
class WindowsTextBox : public TextBox {
public:
void Display() override {
cout << "显示 Windows 风格文本框(白色背景、黑色文字)" << endl;
}
};
// Mac 产品族
class MacButton : public Button {
public:
void Display() override {
cout << "显示 Mac 风格按钮(灰色、圆角)" << endl;
}
};
class MacTextBox : public TextBox {
public:
void Display() override {
cout << "显示 Mac 风格文本框(浅灰色背景、黑色文字)" << endl;
}
};
抽象工厂类声明创建产品族中所有产品的纯虚方法:
// 抽象工厂:UI 组件工厂(创建一个产品族的所有产品)
class UIFactory {
public:
virtual Button* CreateButton() = 0; // 创建按钮
virtual TextBox* CreateTextBox() = 0; // 创建文本框
virtual ~UIFactory() {}
};
// 具体工厂 1:Windows UI 工厂(创建 Windows 产品族)
class WindowsUIFactory : public UIFactory {
public:
Button* CreateButton() override { return new WindowsButton(); }
TextBox* CreateTextBox() override { return new WindowsTextBox(); }
};
// 具体工厂 2:Mac UI 工厂(创建 Mac 产品族)
class MacUIFactory : public UIFactory {
public:
Button* CreateButton() override { return new MacButton(); }
TextBox* CreateTextBox() override { return new MacTextBox(); }
};
// 客户端函数:根据传入的工厂,创建并显示 UI 组件
void ShowUI(UIFactory* factory) {
Button* button = factory->CreateButton();
TextBox* textBox = factory->CreateTextBox();
button->Display();
textBox->Display();
delete button;
delete textBox;
delete factory;
}
int main() {
cout << "=== Windows 平台 UI ===" << endl;
ShowUI(new WindowsUIFactory()); // 使用 Windows 工厂
cout << "\n=== Mac 平台 UI ===" << endl;
ShowUI(new MacUIFactory()); // 使用 Mac 工厂
// 【扩展】新增 Linux 平台时,只需添加 Linux 产品族(LinuxButton、LinuxTextBox)和 LinuxUIFactory,无需修改客户端代码
return 0;
}
运行结果:
=== Windows 平台 UI ===
显示 Windows 风格按钮(蓝色、矩形)
显示 Windows 风格文本框(白色背景、黑色文字)
=== Mac 平台 UI ===
显示 Mac 风格按钮(灰色、圆角)
显示 Mac 风格文本框(浅灰色背景、黑色文字)
✅ 优点:
⚠️ 缺点:
| 模式类型 | 核心特点 | 适用场景 | 扩展方式 |
|---|---|---|---|
| 简单工厂模式 | 一个工厂创建所有产品 | 产品类型少、变化少 | 修改工厂类(违反开放 - 封闭) |
| 工厂方法模式 | 一个产品对应一个工厂 | 产品类型多、需单独扩展 | 新增产品类 + 工厂类(无侵入) |
| 抽象工厂模式 | 一个工厂创建一个产品族 | 需管理多个相关产品族 | 新增产品族(无侵入)、扩展产品等级(困难) |
💡 实战技巧: 大多数场景下,'工厂方法模式'是性价比最高的选择;若需管理相关产品族,再考虑'抽象工厂模式';'简单工厂模式'仅适用于小型、简单的项目。
单例模式(Singleton)是创建型设计模式的另一个核心,其核心思想是'确保一个类在整个系统中只有一个实例,并提供一个全局访问点'。
实际开发中,以下场景需要确保对象唯一:
若不使用单例模式,可能导致:
new 创建实例;GetInstance())。饿汉式(Hungry Singleton):在程序启动时(类加载阶段)就创建实例,无论是否使用,实例都已存在。
#include <iostream>
#include <string>
#include <map>
using namespace std;
// 饿汉式单例:配置管理类(加载系统配置)
class ConfigManager {
private:
// 1. 私有构造函数:禁止外部创建实例
ConfigManager() {
// 模拟加载配置文件(程序启动时执行)
LoadConfig();
cout << "饿汉式单例:配置文件加载完成" << endl;
}
// 2. 私有拷贝构造函数和赋值运算符:禁止拷贝
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
// 3. 静态私有实例:程序启动时初始化
static ConfigManager instance;
// 配置数据存储
map<string, string> configMap;
// 加载配置文件(模拟)
void LoadConfig() {
configMap["db_host"] = "127.0.0.1";
configMap["db_port"] = "3306";
configMap["db_user"] = "root";
configMap["db_pwd"] = "123456";
}
public:
// 4. 静态公有方法:全局访问点
static ConfigManager& GetInstance() {
return instance;
}
// 获取配置值
string GetConfig(const string& key) {
auto iter = configMap.find(key);
if (iter != configMap.end()) {
return iter->second;
}
return "配置不存在";
}
};
// 初始化静态实例(程序启动时执行,线程安全)
ConfigManager ConfigManager::instance;
// 客户端使用
int main() {
// 第一次获取实例(实例已存在)
ConfigManager& config1 = ConfigManager::GetInstance();
cout << "数据库地址:" << config1.GetConfig("db_host") << endl;
// 第二次获取实例(返回同一个实例)
ConfigManager& config2 = ConfigManager::GetInstance();
cout << "数据库端口:" << config2.GetConfig("db_port") << endl;
// 验证是否为同一个实例(地址相同)
cout << "config1 地址:" << &config1 << endl;
cout << "config2 地址:" << &config2 << endl;
return 0;
}
运行结果:
饿汉式单例:配置文件加载完成
数据库地址:127.0.0.1
数据库端口:3306
config1 地址:0x404068
config2 地址:0x404068
✅ 优点:
⚠️ 缺点:
懒汉式(Lazy Singleton):在第一次调用 GetInstance() 时才创建实例,实现'延迟加载',节省内存。
naive 的懒汉式实现(非线程安全):
class Singleton {
private:
static Singleton* instance;
Singleton() {}
public:
static Singleton* GetInstance() {
if (instance == nullptr) {
instance = new Singleton(); // 多线程下可能创建多个实例
}
return instance;
}
};
Singleton* Singleton::instance = nullptr;
问题:多线程环境下,若两个线程同时进入 if (instance == nullptr),会导致创建多个实例,违反单例原则。
C++11 标准规定:局部静态变量的初始化是线程安全的(在初始化完成前,其他线程会阻塞)。利用这一特性,可实现简洁、高效的线程安全懒汉式单例。
#include <iostream>
#include <string>
#include <fstream>
#include <mutex>
#include <thread>
using namespace std;
// 线程安全的懒汉式单例:日志管理器
class LogManager {
private:
// 私有构造函数(延迟初始化)
LogManager() {
cout << "懒汉式单例:日志管理器初始化" << endl;
}
// 禁止拷贝
LogManager(const LogManager&) = delete;
LogManager& operator=(const LogManager&) = delete;
// 日志文件路径
string logFilePath = "app.log";
public:
// 静态公有方法:全局访问点(C++11 线程安全)
static LogManager& GetInstance() {
static LogManager instance; // 局部静态变量,第一次调用时初始化(线程安全)
return instance;
}
// 写入日志
void WriteLog(const string& level, const string& message) {
ofstream logFile(logFilePath, ios::app);
if (logFile.is_open()) {
logFile << "[" << level << "] " << message << endl;
logFile.close();
} else {
throw runtime_error("日志文件打开失败!");
}
}
};
// 多线程测试(验证线程安全)
void TestThread(int threadId) {
string message = "线程" + to_string(threadId) + "执行日志";
LogManager::GetInstance().WriteLog("INFO", message);
}
int main() {
cout << "程序启动,未创建日志实例" << endl;
// 第一次调用:创建实例
LogManager::GetInstance().WriteLog("INFO", "系统启动成功");
// 多线程测试(10 个线程同时调用)
thread threads[10];
for (int i = 0; i < 10; ++i) {
threads[i] = thread(TestThread, i);
}
for (int i = 0; i < 10; ++i) {
threads[i].join();
}
cout << "日志写入完成,查看 app.log 文件" << endl;
return 0;
}
运行结果:
程序启动,未创建日志实例
懒汉式单例:日志管理器初始化
日志写入完成,查看 app.log 文件
app.log 文件内容:
[INFO] 系统启动成功
[INFO] 线程 0 执行日志
[INFO] 线程 1 执行日志
...
[INFO] 线程 9 执行日志
✅ 优点:
⚠️ 缺点:
std::mutex),但会引入性能开销;若未禁用拷贝构造函数和赋值运算符,可能通过以下方式创建新实例:
ConfigManager config3 = ConfigManager::GetInstance(); // 调用拷贝构造函数
✅ 避坑方案: 显式删除拷贝构造函数和赋值运算符(C++11 及以上):
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
naive 懒汉式在多线程下会创建多个实例,即使手动加锁,也可能存在'双重检查锁定'的坑(如指令重排导致的空指针)。
✅ 避坑方案: 优先使用 C++11 局部静态变量的实现方式,无需手动处理线程安全。
若单例对象依赖其他全局对象,可能出现'单例已析构,但其他对象仍在使用它'的情况。
✅ 避坑方案:
将单例模式当作'全局变量'滥用,会导致:
✅ 避坑方案: 仅在确实需要'全局唯一实例'的场景下使用单例(如配置、日志、连接池),避免将单例作为全局变量的替代品。
开发一个支持多日志类型(控制台、文件、数据库)且可配置的日志系统,要求:
LogSystem)为单例,确保全局唯一;ConfigManager 加载日志类型配置,由 LogSystem 自动选择对应的工厂创建日志器。#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <thread>
using namespace std;
// -------------------------- 步骤 1:单例配置管理器 --------------------------
class ConfigManager {
private:
ConfigManager() { LoadConfig(); }
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
static ConfigManager& GetInstance() {
static ConfigManager instance;
return instance;
}
map<string, string> configMap;
void LoadConfig() {
// 模拟加载配置文件:日志类型配置为 "file"(支持 "console"、"db"、"file")
configMap["log_type"] = "file";
configMap["log_file"] = "system.log";
}
public:
// 提供全局访问接口,获取配置值
static string GetConfig(const string& key) {
return GetInstance().configMap[key];
}
};
// -------------------------- 步骤 2:工厂模式 - 日志器与工厂 --------------------------
// 日志器抽象基类
class Logger {
public:
virtual void WriteLog(const string& level, const string& message) = 0;
virtual ~Logger() {}
};
// 具体日志器:控制台日志
class ConsoleLogger : public Logger {
public:
void WriteLog(const string& level, const string& message) override {
cout << "[" << level << "] [控制台] " << message << endl;
}
};
// 具体日志器:文件日志
class FileLogger : public Logger {
private:
string logFile;
public:
FileLogger(const string& filePath) : logFile(filePath) {}
void WriteLog(const string& level, const string& message) override {
ofstream file(logFile, ios::app);
if (file.is_open()) {
file << "[" << level << "] [文件] " << message << endl;
file.close();
} else {
throw runtime_error("无法打开日志文件:" + logFile);
}
}
};
// 具体日志器:数据库日志
class DatabaseLogger : public Logger {
public:
void WriteLog(const string& level, const string& message) override {
cout << "[" << level << "] [数据库] " << message << endl;
}
};
// 日志工厂抽象基类
class LoggerFactory {
public:
virtual Logger* CreateLogger() = 0;
virtual ~LoggerFactory() {}
};
// 具体工厂:控制台日志工厂
class ConsoleLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override { return new ConsoleLogger(); }
};
// 具体工厂:文件日志工厂(从配置获取文件路径)
class FileLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override {
string logFile = ConfigManager::GetConfig("log_file");
return new FileLogger(logFile);
}
};
// 具体工厂:数据库日志工厂
class DatabaseLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override { return new DatabaseLogger(); }
};
// -------------------------- 步骤 3:单例日志系统核心 --------------------------
class LogSystem {
private:
LogSystem() {
// 从配置获取日志类型,创建对应的工厂和日志器
string logType = ConfigManager::GetConfig("log_type");
factory = CreateLoggerFactory(logType);
logger = factory->CreateLogger();
cout << "日志系统初始化完成,当前日志类型:" << logType << endl;
}
LogSystem(const LogSystem&) = delete;
LogSystem& operator=(const LogSystem&) = delete;
// 根据日志类型创建工厂
LoggerFactory* CreateLoggerFactory(const string& logType) {
if (logType == "console") {
return new ConsoleLoggerFactory();
} else if (logType == "file") {
return new FileLoggerFactory();
} else if (logType == "db") {
return new DatabaseLoggerFactory();
} else {
throw invalid_argument("不支持的日志类型:" + logType);
}
}
static LogSystem& GetInstance() {
static LogSystem instance;
return instance;
}
LoggerFactory* factory;
Logger* logger;
public:
// 全局日志写入接口
static void Log(const string& level, const string& message) {
GetInstance().logger->WriteLog(level, message);
}
// 析构时释放资源
~LogSystem() {
delete logger;
delete factory;
}
};
// -------------------------- 客户端测试 --------------------------
void TestLog(int moduleId) {
string message = "模块" + to_string(moduleId) + "执行完成";
LogSystem::Log("INFO", message);
}
int main() {
try {
// 1. 单线程测试
LogSystem::Log("DEBUG", "系统启动中...");
LogSystem::Log("INFO", "系统启动成功");
LogSystem::Log("WARN", "内存使用率过高(80%)");
LogSystem::Log("ERROR", "数据库连接超时");
// 2. 多线程测试(10 个模块同时写入日志)
thread modules[10];
for (int i = 0; i < 10; ++i) {
modules[i] = thread(TestLog, i);
}
for (int i = 0; i < 10; ++i) {
modules[i].join();
}
cout << "日志写入完成,查看 system.log 文件" << endl;
} catch (const exception& e) {
cout << "日志系统错误:" << e.what() << endl;
}
return 0;
}
LogSystem 是单例,确保全局唯一;内部通过工厂模式创建日志器,支持扩展;ConfigManager 配置,修改配置即可切换日志类型(如将 log_type 改为 'console' 则切换为控制台日志);LogSystem 和 ConfigManager 均使用 C++11 局部静态变量实现单例,支持多线程安全访问。日志系统初始化完成,当前日志类型:file
[DEBUG] [文件] 系统启动中...
[INFO] [文件] 系统启动成功
[WARN] [文件] 内存使用率过高(80%)
[ERROR] [文件] 数据库连接超时
日志写入完成,查看 system.log 文件
system.log 文件内容:
[DEBUG] [文件] 系统启动中...
[INFO] [文件] 系统启动成功
[WARN] [文件] 内存使用率过高(80%)
[ERROR] [文件] 数据库连接超时
[INFO] [文件] 模块 0 执行完成
[INFO] [文件] 模块 1 执行完成
...
[INFO] [文件] 模块 9 执行完成
若需新增'网络日志',只需添加以下代码,无需修改现有核心代码:
// 新增具体日志器:网络日志
class NetworkLogger : public Logger {
public:
void WriteLog(const string& level, const string& message) override {
cout << "[" << level << "] [网络] 发送日志到服务器:" << message << endl;
}
};
// 新增具体工厂:网络日志工厂
class NetworkLoggerFactory : public LoggerFactory {
public:
Logger* CreateLogger() override { return new NetworkLogger(); }
};
// 修改配置文件(或 ConfigManager 的 LoadConfig 方法)
configMap["log_type"] = "network";
// 在 LogSystem::CreateLoggerFactory 中添加分支
else if (logType == "network") {
return new NetworkLoggerFactory();
}
本章重点讲解了 C++ 开发中最常用的两种设计模式:工厂模式和单例模式,核心要点总结如下:
通过本章学习,你应能在实际项目中灵活运用工厂模式和单例模式,解决对象创建和全局实例管理的问题,编写高内聚、低耦合的优质 C++ 代码。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online