常见设计模式

目录

一、设计模式基础认知

[1. 什么是设计模式?](#1. 什么是设计模式?)

[2. 设计模式的核心分类](#2. 设计模式的核心分类)

[3. Linux C++设计模式核心原则](#3. Linux C++设计模式核心原则)

二、创建型模式:精准控制对象创建

[1. 单例模式(Singleton)------ 全局唯一实例](#1. 单例模式(Singleton)—— 全局唯一实例)

[1. 核心原理](#1. 核心原理)

[2. Linux C++实现(三种方案,按优先级排序)](#2. Linux C++实现(三种方案,按优先级排序))

[3. Linux实战场景与面试考点](#3. Linux实战场景与面试考点)

[2. 工厂方法模式(Factory Method)------ 封装对象创建](#2. 工厂方法模式(Factory Method)—— 封装对象创建)

[1. 核心原理](#1. 核心原理)

[2. Linux C++实现(协议解析场景)](#2. Linux C++实现(协议解析场景))

[3. 优化与场景](#3. 优化与场景)

[3. 其他创建型模式](#3. 其他创建型模式)

三、结构型模式:优化对象组合与适配

[1. 适配器模式(Adapter)------ 接口兼容转换](#1. 适配器模式(Adapter)—— 接口兼容转换)

[1. 核心原理](#1. 核心原理)

[2. Linux C++实现(系统调用适配场景)](#2. Linux C++实现(系统调用适配场景))

[3. 实战场景](#3. 实战场景)

[2. 代理模式(Proxy)------ 资源管控与增强](#2. 代理模式(Proxy)—— 资源管控与增强)

[1. 核心原理](#1. 核心原理)

[2. Linux C++实现(权限代理场景)](#2. Linux C++实现(权限代理场景))

[3. 装饰器模式(Decorator)------ 动态增强功能](#3. 装饰器模式(Decorator)—— 动态增强功能)

四、行为型模式:规范对象交互(服务器核心)

[1. 观察者模式(Observer)------ 事件通知机制](#1. 观察者模式(Observer)—— 事件通知机制)

[1. 核心原理](#1. 核心原理)

[2. Linux C++实现(服务器连接事件通知)](#2. Linux C++实现(服务器连接事件通知))

[3. 注意事项](#3. 注意事项)

[2. 策略模式(Strategy)------ 动态切换算法](#2. 策略模式(Strategy)—— 动态切换算法)

[3. 模板方法模式(Template Method)------ 框架钩子设计](#3. 模板方法模式(Template Method)—— 框架钩子设计)

五、设计模式组合应用(Linux服务器案例)

[1. Linux高性能日志服务器](#1. Linux高性能日志服务器)

[1. 架构设计(多模式组合)](#1. 架构设计(多模式组合))

[2. 核心代码框架](#2. 核心代码框架)

六、补充知识点

[1. 单例模式的线程安全实现方案对比?Linux内核与用户态实现差异?](#1. 单例模式的线程安全实现方案对比?Linux内核与用户态实现差异?)

[2. 工厂方法与抽象工厂的区别?Linux场景下如何选择?](#2. 工厂方法与抽象工厂的区别?Linux场景下如何选择?)

[3. 观察者模式在多线程场景下的线程安全问题如何解决?](#3. 观察者模式在多线程场景下的线程安全问题如何解决?)

[4. 适配器模式与装饰器模式的核心差异?各自适用场景?](#4. 适配器模式与装饰器模式的核心差异?各自适用场景?)

[5. 设计模式过度使用的危害?Linux项目中如何把握度?](#5. 设计模式过度使用的危害?Linux项目中如何把握度?)

[6. 单例模式在Linux服务器集群场景下的局限性?如何解决?](#6. 单例模式在Linux服务器集群场景下的局限性?如何解决?)


设计模式是解决软件设计中重复问题的标准化方案,是Linux C++开发从"能实现"到"写优雅、可扩展、高可靠代码"的核心桥梁。

一、设计模式基础认知

1. 什么是设计模式?

设计模式是对"软件设计中反复出现的问题、解决方案、场景约束"的总结提炼,本质是可复用的架构经验模板。它不是现成代码,而是一套设计思路,核心目标是:

  • 解耦:分离模块职责,降低组件间依赖(如Linux服务器中业务逻辑与网络IO解耦)。
  • 可扩展:新增功能无需修改原有代码(如新增日志输出方式、协议类型)。
  • 可维护:代码逻辑清晰、符合直觉,便于定位问题与迭代(如内核模块的分层设计)。
  • 高可靠:规避资源泄漏、线程安全等常见坑(如单例模式的线程安全实现)。

类比:设计模式像Linux系统的"命令范式"------ls、cd等命令对应固定场景的解决方案,无需重复造轮子;设计模式对应软件设计的"场景范式",如"全局唯一实例"用单例模式,"多模块通知"用观察者模式。

2. 设计模式的核心分类
分类 核心目标 Linux C++高频模式 典型场景
创建型模式 控制对象创建过程,隐藏创建细节,优化资源分配 单例、工厂方法、抽象工厂、建造者 日志器、线程池、配置解析器、对象池
结构型模式 优化对象组合关系,实现灵活的结构适配与功能扩展 适配器、装饰器、代理、组合 系统调用封装、日志增强、权限代理、目录树遍历
行为型模式 规范对象间交互行为,实现职责分配与通信解耦 观察者、策略、模板方法、命令 服务器事件通知、算法切换、框架钩子、任务队列
3. Linux C++设计模式核心原则

设计模式的底层逻辑围绕5大原则展开,是判断代码设计优劣的核心标准:

  • 单一职责:一个类只负责一项功能(如Linux日志类只处理日志,不负责配置读取)。
  • 开放封闭:对扩展开放、对修改关闭(如新增日志输出到文件,无需修改日志核心逻辑)。
  • 依赖倒置:依赖抽象而非具体实现(如线程池依赖"任务抽象接口",而非具体业务任务)。
  • 接口隔离:拆分庞大接口为专用接口(如Linux驱动接口拆分,避免依赖无用方法)。
  • 里氏替换:子类可替换父类且不改变原有逻辑(如不同协议解析子类替换,不影响上层调用)。

二、创建型模式:精准控制对象创建

1. 单例模式(Singleton)------ 全局唯一实例
1. 核心原理

保证一个类在全局只有一个实例,提供唯一访问入口,避免重复创建对象导致的资源浪费(如Linux日志器、配置管理器)。核心约束:私有构造函数、静态实例、静态访问方法。

2. Linux C++实现(三种方案,按优先级排序)
cpp 复制代码
#include <iostream>
#include <pthread.h>
#include <atomic>

using namespace std;

// 方案1:C++11静态局部变量(推荐,线程安全、简洁)
class Singleton {
private:
  // 私有构造/析构,禁止外部创建/销毁
  Singleton() { /* 初始化资源,如打开日志文件 */ }
  ~Singleton() { /* 释放资源,如关闭文件 */ }
  // 禁止拷贝/赋值
  Singleton(const Singleton&) = delete;
  Singleton& operator=(const Singleton&) = delete;

public:
  // 静态访问接口,C++11保证静态局部变量初始化线程安全
  static Singleton& GetInstance() {
    static Singleton instance;  // 首次调用时初始化,仅一次
    return instance;
  }

  // 业务方法(示例:日志输出)
  void Log(const string& msg) {
    cout << "[Log] " << msg << endl;
  }
};

// 方案2:懒汉模式(双重检查锁定,兼容C++11前)
class SingletonLazy {
private:
  SingletonLazy() {}
  ~SingletonLazy() {}
  SingletonLazy(const SingletonLazy&) = delete;
  SingletonLazy& operator=(const SingletonLazy&) = delete;

  static atomic<SingletonLazy*> instance;  // 原子变量保证线程安全
  static pthread_mutex_t mutex;             // 互斥锁

public:
  static SingletonLazy* GetInstance() {
    SingletonLazy* ptr = instance.load(memory_order_acquire);
    if (!ptr) {  // 第一次检查,避免每次加锁
      pthread_mutex_lock(&mutex);
      ptr = instance.load(memory_order_relaxed);
      if (!ptr) {  // 第二次检查,防止多线程并发创建
        ptr = new SingletonLazy();
        instance.store(ptr, memory_order_release);
      }
      pthread_mutex_unlock(&mutex);
    }
    return ptr;
  }

  // 手动释放(可选,适用于内核模块等无析构时机场景)
  static void DestroyInstance() {
    SingletonLazy* ptr = instance.load(memory_order_acquire);
    if (ptr) {
      delete ptr;
      instance.store(nullptr, memory_order_release);
    }
  }
};

// 初始化静态成员
atomic<SingletonLazy*> SingletonLazy::instance(nullptr);
pthread_mutex_t SingletonLazy::mutex = PTHREAD_MUTEX_INITIALIZER;

// 方案3:饿汉模式(预初始化,线程安全但浪费资源)
class SingletonHungry {
private:
  SingletonHungry() {}
  ~SingletonHungry() {}
  SingletonHungry(const SingletonHungry&) = delete;
  SingletonHungry& operator=(const SingletonHungry&) = delete;

  static SingletonHungry instance;  // 程序启动时初始化

public:
  static SingletonHungry& GetInstance() {
    return instance;
  }
};

SingletonHungry SingletonHungry::instance;  // 全局静态变量初始化

// 测试代码
int main() {
  // 方案1调用
  Singleton::GetInstance().Log("Hello Linux Singleton");
  // 方案2调用
  SingletonLazy::GetInstance()->Log("Lazy Singleton Test");
  // 方案3调用
  SingletonHungry::GetInstance().Log("Hungry Singleton Test");

  SingletonLazy::DestroyInstance();
  return 0;
}
3. Linux实战场景与面试考点

实战场景:系统日志器、全局配置管理器、线程池实例、内核模块中的全局控制器。

面试考点

  • 线程安全实现:C++11静态局部变量的线程安全原理(编译器生成初始化屏障)、双重检查锁定的原子操作必要性(避免指令重排)。
  • 销毁时机:用户态程序依赖析构函数自动销毁,内核模块需手动调用DestroyInstance(无进程退出析构时机)。
  • 优缺点对比:饿汉(简单但预占资源)、懒汉(按需初始化但需锁)、静态局部变量(兼顾简洁与安全,推荐生产使用)。
2. 工厂方法模式(Factory Method)------ 封装对象创建
1. 核心原理

定义一个创建对象的接口,由子类决定具体创建哪种对象,实现"创建与使用分离"。适用于Linux中"同一接口、多种实现"场景(如不同协议解析器、不同存储引擎)。

2. Linux C++实现(协议解析场景)
cpp 复制代码
#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

// 抽象产品:协议解析器接口
class IProtocolParser {
public:
  virtual ~IProtocolParser() {}  // 虚析构,保证子类析构
  virtual string Parse(const string& data) = 0;  // 纯虚方法,协议解析
};

// 具体产品1:HTTP协议解析器
class HttpParser : public IProtocolParser {
public:
  string Parse(const string& data) override {
    return "[HTTP] Parse Data: " + data;
  }
};

// 具体产品2:TCP协议解析器
class TcpParser : public IProtocolParser {
public:
  string Parse(const string& data) override {
    return "[TCP] Parse Data: " + data;
  }
};

// 抽象工厂:协议解析器工厂接口
class IProtocolFactory {
public:
  virtual ~IProtocolFactory() {}
  virtual IProtocolParser* CreateParser() = 0;  // 工厂方法
};

// 具体工厂1:HTTP工厂
class HttpFactory : public IProtocolFactory {
public:
  IProtocolParser* CreateParser() override {
    return new HttpParser();
  }
};

// 具体工厂2:TCP工厂
class TcpFactory : public IProtocolFactory {
public:
  IProtocolParser* CreateParser() override {
    return new TcpParser();
  }
};

// Linux服务端调用示例
int main() {
  // 模拟根据配置选择协议工厂
  string protocol_type = "HTTP";  // 可从配置文件读取
  IProtocolFactory* factory = nullptr;

  if (protocol_type == "HTTP") {
    factory = new HttpFactory();
  } else if (protocol_type == "TCP") {
    factory = new TcpFactory();
  }

  // 创建解析器并使用
  if (factory) {
    IProtocolParser* parser = factory->CreateParser();
    cout << parser->Parse("GET /index.html HTTP/1.1") << endl;
    delete parser;
    delete factory;
  }

  return 0;
}
3. 优化与场景

优化点:1. 结合单例模式,让工厂实例全局唯一;2. 用智能指针(unique_ptr/shared_ptr)管理对象,避免内存泄漏;3. 增加工厂注册机制(哈希表),支持动态扩展协议类型。

实战场景:Linux服务器协议解析模块、数据库中间件存储引擎适配、日志输出器工厂(控制台/文件/网络日志)。

3. 其他创建型模式
  • 抽象工厂模式:工厂方法的扩展,用于创建"一组相关联的对象"(如Linux GUI中的按钮、文本框属于同一主题),适用于成套组件创建场景。
  • 建造者模式:拆分复杂对象的构建过程,分步构建(如Linux内核进程控制块PCB的创建,分步初始化PID、内存空间、文件描述符),适用于对象构造逻辑复杂场景。

三、结构型模式:优化对象组合与适配

1. 适配器模式(Adapter)------ 接口兼容转换
1. 核心原理

将一个类的接口转换成客户端期望的另一个接口,解决不同接口间的兼容性问题(如Linux系统调用封装、第三方库接口适配)。分为类适配器(继承)和对象适配器(组合,推荐)。

2. Linux C++实现(系统调用适配场景)
cpp 复制代码
#include <iostream>
#include <unistd.h>  // Linux系统调用头文件
#include <string>

using namespace std;

// 目标接口:客户端期望的文件操作接口(统一封装)
class IFileOperator {
public:
  virtual ~IFileOperator() {}
  virtual bool Write(const string& data) = 0;  // 写入数据
  virtual bool Close() = 0;                   // 关闭文件
};

// 适配者:Linux原生系统调用(接口不统一,需适配)
class LinuxFileSys {
public:
  // 原生系统调用封装
  int Open(const string& path) {
    return open(path.c_str(), O_WRONLY | O_CREAT, 0644);  // 打开/创建文件
  }
  ssize_t Write(int fd, const string& data) {
    return write(fd, data.c_str(), data.size());  // 原生写入
  }
  int Close(int fd) {
    return close(fd);  // 原生关闭
  }
private:
  int fd_ = -1;  // 文件描述符
};

// 对象适配器:组合适配者,实现目标接口
class FileAdapter : public IFileOperator {
public:
  FileAdapter(const string& path) : path_(path) {}
  ~FileAdapter() {
    if (fd_ != -1) {
      linux_file_.Close(fd_);
    }
  }

  // 适配Write接口
  bool Write(const string& data) override {
    if (fd_ == -1) {
      fd_ = linux_file_.Open(path_);
      if (fd_ == -1) {
        cerr << "Open file failed: " << strerror(errno) << endl;
        return false;
      }
    }
    ssize_t ret = linux_file_.Write(fd_, data);
    return ret == data.size();
  }

  // 适配Close接口
  bool Close() override {
    if (fd_ != -1) {
      int ret = linux_file_.Close(fd_);
      fd_ = -1;
      return ret == 0;
    }
    return true;
  }

private:
  LinuxFileSys linux_file_;  // 组合适配者
  string path_;              // 文件路径
  int fd_ = -1;              // 文件描述符
};

// 客户端调用(无需关心原生系统调用,依赖统一接口)
int main() {
  IFileOperator* file_op = new FileAdapter("/tmp/adapter_test.txt");
  if (file_op->Write("Hello Linux Adapter Pattern")) {
    cout << "Write success" << endl;
  }
  file_op->Close();
  delete file_op;
  return 0;
}
3. 实战场景

Linux系统调用封装(如将open/write/close适配为统一文件接口)、第三方库接口适配(如不同日志库适配为自定义日志接口)、内核驱动接口适配(将不同硬件驱动适配为统一内核接口)。

2. 代理模式(Proxy)------ 资源管控与增强
1. 核心原理

为对象提供一个代理类,控制对原对象的访问,可实现权限校验、资源缓存、日志增强等功能(如Linux权限代理、远程服务代理)。

2. Linux C++实现(权限代理场景)
cpp 复制代码
#include <iostream>
#include <string>
#include <unistd.h>  // 获取用户ID

using namespace std;

// 抽象主题:文件操作接口
class IFileAccess {
public:
  virtual ~IFileAccess() {}
  virtual bool Read(const string& path) = 0;
  virtual bool Write(const string& path, const string& data) = 0;
};

// 真实主题:实际文件操作
class RealFileAccess : public IFileAccess {
public:
  bool Read(const string& path) override {
    cout << "Read file: " << path << endl;
    return true;
  }

  bool Write(const string& path, const string& data) override {
    cout << "Write file: " << path << ", Data: " << data << endl;
    return true;
  }
};

// 代理类:权限校验代理(Linux用户权限控制)
class PermissionProxy : public IFileAccess {
public:
  PermissionProxy(IFileAccess* real_access) : real_access_(real_access) {}
  ~PermissionProxy() {
    delete real_access_;
  }

  bool Read(const string& path) override {
    // 权限校验:只有root用户(UID=0)可读取
    if (getuid() != 0) {
      cerr << "Permission denied: Only root can read " << path << endl;
      return false;
    }
    return real_access_->Read(path);
  }

  bool Write(const string& path, const string& data) override {
    if (getuid() != 0) {
      cerr << "Permission denied: Only root can write " << path << endl;
      return false;
    }
    return real_access_->Write(path, data);
  }

private:
  IFileAccess* real_access_;  // 真实对象
};

// 客户端调用
int main() {
  IFileAccess* file_access = new PermissionProxy(new RealFileAccess());
  // 非root用户运行时,权限校验失败
  file_access->Read("/etc/passwd");
  file_access->Write("/etc/passwd", "test");
  delete file_access;
  return 0;
}
3. 装饰器模式(Decorator)------ 动态增强功能

动态给对象添加额外功能,无需修改原类代码(符合开放封闭原则)。适用于Linux日志增强、网络IO过滤等场景,比继承更灵活。

实战场景:给基础日志器添加"时间戳装饰""级别过滤装饰",给网络请求添加"加密装饰""日志装饰"。

四、行为型模式:规范对象交互(服务器核心)

1. 观察者模式(Observer)------ 事件通知机制
1. 核心原理

定义对象间的一对多依赖关系,当一个对象状态变化时,所有依赖它的对象会自动收到通知并更新。适用于Linux事件驱动场景(如服务器连接事件、内核信号通知)。

2. Linux C++实现(服务器连接事件通知)
cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <pthread.h>

using namespace std;

// 前向声明
class Subject;

// 抽象观察者:事件接收接口
class Observer {
public:
  virtual ~Observer() {}
  virtual void Update(const string& event) = 0;  // 事件更新
};

// 抽象主题:事件发布者
class Subject {
public:
  virtual ~Subject() {}
  // 注册观察者
  virtual void Attach(Observer* observer) {
    pthread_mutex_lock(&mutex_);
    observers_.push_back(observer);
    pthread_mutex_unlock(&mutex_);
  }
  // 移除观察者
  virtual void Detach(Observer* observer) {
    pthread_mutex_lock(&mutex_);
    auto it = find(observers_.begin(), observers_.end(), observer);
    if (it != observers_.end()) {
      observers_.erase(it);
    }
    pthread_mutex_unlock(&mutex_);
  }
  // 通知所有观察者
  virtual void Notify(const string& event) {
    pthread_mutex_lock(&mutex_);
    for (auto observer : observers_) {
      observer->Update(event);
    }
    pthread_mutex_unlock(&mutex_);
  }

private:
  vector<Observer*> observers_;  // 观察者列表
  pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;  // 线程安全锁
};

// 具体主题:服务器连接管理器
class ConnectionManager : public Subject {
public:
  // 模拟新连接事件
  void OnNewConnection(const string& client_ip) {
    string event = "New connection from " + client_ip;
    Notify(event);  // 通知所有观察者
  }
  // 模拟连接断开事件
  void OnDisconnect(const string& client_ip) {
    string event = "Disconnect from " + client_ip;
    Notify(event);
  }
};

// 具体观察者1:日志观察者
class LogObserver : public Observer {
public:
  void Update(const string& event) override {
    cout << "[Log Observer] " << event << endl;
  }
};

// 具体观察者2:统计观察者
class StatObserver : public Observer {
public:
  void Update(const string& event) override {
    static int conn_count = 0;
    if (event.find("New connection") != string::npos) {
      conn_count++;
    } else if (event.find("Disconnect") != string::npos) {
      conn_count--;
    }
    cout << "[Stat Observer] Current connections: " << conn_count << endl;
  }
};

// 测试:多线程模拟事件触发
void* SimulateEvents(void* arg) {
  ConnectionManager* manager = (ConnectionManager*)arg;
  // 模拟客户端连接/断开
  manager->OnNewConnection("192.168.1.1");
  sleep(1);
  manager->OnNewConnection("192.168.1.2");
  sleep(1);
  manager->OnDisconnect("192.168.1.1");
  return nullptr;
}

int main() {
  ConnectionManager manager;
  LogObserver log_observer;
  StatObserver stat_observer;

  // 注册观察者
  manager.Attach(&log_observer);
  manager.Attach(&stat_observer);

  // 启动线程模拟事件
  pthread_t tid;
  pthread_create(&tid, nullptr, SimulateEvents, &manager);
  pthread_join(tid, nullptr);

  // 移除观察者
  manager.Detach(&log_observer);
  manager.Detach(&stat_observer);

  return 0;
}
3. 注意事项
  • 线程安全:观察者列表的增删改查需加互斥锁(如pthread_mutex_t),避免多线程并发问题。
  • 避免循环依赖:观察者与主题尽量避免互相持有强引用,可使用弱指针(weak_ptr)。
  • 异步通知:高并发场景下,可将通知逻辑放入线程池异步执行,避免阻塞主题线程。
2. 策略模式(Strategy)------ 动态切换算法

定义一系列算法,封装成独立类,可动态切换算法而不修改调用代码。适用于Linux中"同一任务多种实现"场景(如压缩算法、排序算法、加密算法切换)。

3. 模板方法模式(Template Method)------ 框架钩子设计

定义一个操作的骨架流程,将可变步骤延迟到子类实现。适用于Linux框架设计(如内核驱动框架、服务器请求处理框架),规范流程并保留扩展点。

五、设计模式组合应用(Linux服务器案例)

单一模式难以应对复杂场景,结合Linux高性能服务器设计,展示多模式组合用法,提供可落地的架构思路。

1. Linux高性能日志服务器
1. 架构设计(多模式组合)
  • 单例模式:日志器全局唯一实例,避免重复创建资源。
  • 工厂方法模式:日志输出器工厂(控制台/文件/网络输出),支持动态扩展。
  • 装饰器模式:给日志添加时间戳、级别过滤、加密装饰。
  • 观察者模式:日志事件通知(如异常日志触发告警)。
2. 核心代码框架
cpp 复制代码
#include <iostream>
#include <string>
#include <memory>  // 智能指针

using namespace std;

// 1. 日志输出器接口(工厂方法产品)
class ILogger {
public:
  virtual ~ILogger() {}
  virtual void Log(const string& msg) = 0;
};

// 具体日志输出器(文件/控制台)
class FileLogger : public ILogger {
public:
  void Log(const string& msg) override {
    cout << "[File Logger] " << msg << endl;
  }
};

class ConsoleLogger : public ILogger {
public:
  void Log(const string& msg) override {
    cout << "[Console Logger] " << msg << endl;
  }
};

// 日志输出器工厂
class LoggerFactory {
public:
  static unique_ptr<ILogger> CreateLogger(const string& type) {
    if (type == "file") {
      return make_unique<FileLogger>();
    } else if (type == "console") {
      return make_unique<ConsoleLogger>();
    }
    return nullptr;
  }
};

// 2. 装饰器基类
class LoggerDecorator : public ILogger {
public:
  LoggerDecorator(unique_ptr<ILogger> logger) : logger_(move(logger)) {}
  void Log(const string& msg) override = 0;

protected:
  unique_ptr<ILogger> logger_;
};

// 时间戳装饰器
class TimeDecorator : public LoggerDecorator {
public:
  TimeDecorator(unique_ptr<ILogger> logger) : LoggerDecorator(move(logger)) {}
  void Log(const string& msg) override {
    // 模拟获取时间戳
    string timestamp = "[2024-05-01 12:00:00]";
    logger_->Log(timestamp + " " + msg);
  }
};

// 3. 单例日志管理器(组合工厂与装饰器)
class LogManager {
public:
  static LogManager& GetInstance() {
    static LogManager instance;
    return instance;
  }

  void Init(const string& logger_type) {
    // 工厂创建日志器,装饰器增强
    auto logger = LoggerFactory::CreateLogger(logger_type);
    if (logger) {
      logger_ = make_unique<TimeDecorator>(move(logger));
    }
  }

  void Log(const string& msg) {
    if (logger_) {
      logger_->Log(msg);
    }
  }

private:
  LogManager() {}
  ~LogManager() {}
  LogManager(const LogManager&) = delete;
  LogManager& operator=(const LogManager&) = delete;

  unique_ptr<ILogger> logger_;
};

// 测试
int main() {
  // 初始化日志管理器(控制台输出+时间戳)
  LogManager::GetInstance().Init("console");
  LogManager::GetInstance().Log("Server started successfully");
  LogManager::GetInstance().Log("Received client request");

  return 0;
}

六、补充知识点

1. 单例模式的线程安全实现方案对比?Linux内核与用户态实现差异?

方案(静态局部变量/双重检查锁定/饿汉);线程安全原理(编译器屏障/原子操作/预初始化);内核与用户态差异(内核无进程退出析构时机,需手动销毁;用户态可依赖析构函数)。

2. 工厂方法与抽象工厂的区别?Linux场景下如何选择?

区别(工厂方法创建单一产品,抽象工厂创建成套产品);选型(单一产品扩展选工厂方法,如协议解析;成套组件创建选抽象工厂,如GUI主题组件)。

3. 观察者模式在多线程场景下的线程安全问题如何解决?

问题(观察者列表并发修改、通知逻辑阻塞);解决方案(互斥锁保护列表、异步通知(线程池)、弱指针避免循环依赖)。

4. 适配器模式与装饰器模式的核心差异?各自适用场景?

差异(适配器解决接口兼容,不改变原功能;装饰器增强原功能,不改变接口);场景(适配器用于接口转换,如系统调用封装;装饰器用于功能扩展,如日志增强)。

5. 设计模式过度使用的危害?Linux项目中如何把握度?

危害(代码复杂度上升、性能开销、可读性下降);把握原则(简单场景不用模式,如单一对象创建;复杂场景(可扩展、解耦)按需使用,优先选择轻量级模式)。

6. 单例模式在Linux服务器集群场景下的局限性?如何解决?

局限性(单例仅进程内唯一,集群多进程场景无法保证全局唯一);解决方案(结合分布式锁(如Redis)、集群配置中心,实现分布式全局唯一)。

相关推荐
杨充20 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充20 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充20 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充20 小时前
2.面向对象的特性
设计模式
杨充20 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充20 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充20 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式