单例模式:从基础实现到高级应用

单例模式:从基础实现到高级应用

单例模式的核心思想

目的:去报一个类仅有一个实例,并提供全局访问点。

适用场景:

  1. 需要严格控制资源访问(如数据库连接池);
  2. 频繁的创建销毁对象成本高(如配置管理器);
  3. 共享状态管理(如全局计数器);

2种经典实现方式及对比

  1. 饿汉式(线程安全)
c++ 复制代码
class Singleton 
{
priveate:
	static Singleton instance;   //类加载时初始化
	Singleton() = default;	//私有构造函数
	~Singleton() = default;
public:
	static Singleton* getSingleton() 
	{
		return &instance;
	}
	
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
}

//初始化静态成员
Singleton Singleton::instance;

特点:

  • 线程安全
  • 可能造成资源浪费(即使不用也会初始化)
  1. 懒汉式(非线程安全)
c++ 复制代码
class Singleton
{
private: 
	static Singleton* instance;   //静态实例指针
	Singleton() = default;		//私有构造函数
	~Singleton() = default;
public:
	static Singleton* getInstance() 
	{
		if (instance == NULL)			//线程不安全点
		{
			instance = new Singleton();
		}
		return instance;
	}
	
	//删除拷贝构造和复制构造操作
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
};

问题:多线程下可能创建多个实例

  1. meyer's singleton(C++最佳实践)
c++ 复制代码
class Singleton
{
public:
	static Singleton& getIntance() 
	{
		static Singleton instance;		//C++11保证线程安全
		return instance;	
	}
private:
	Singleton() = default;
	~Singleton() = default;	
};

单例模式的潜在问题与解决方案

1. 防止反射/克隆破化单例

c++ 复制代码
clasee Singleton
{
	//...其他代码...
private:
	//防止通过反射构造
	Singleton() 
	{
		if (instance != NULL)
		{
			throw std::runtime_error("Singleton already exists!");
		}
	}
};

2.处理析构问题

c++ 复制代码
//方案1:智能指针自动管理
static std::shared_ptr<Singleton> getInstance() {
	static std::shared_ptr<Singleton> instance(new Singleton());
	return instance;
}

//方案2:显示释放接口
static void destoryInstance() {
	delete instance;  //需要配合线程安全处理
}

3. 继承单例基类

c++ 复制代码
template<typedef T>
class Singleton {
projected:
	Singleton() = default;
	~Singleton() = default;
public:
	static T& getSingleton() {
		static T instance;
		return instance;
	}

	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
};

//使用示例
class MyClass : public Singletong<MyClass> {
	friend class Singleton<MyClass>;
private:
	MyClass() = default;
}

单例模式在工程中的实际应用

1. 日志系统

c++ 复制代码
class Logger : public Singleton<Logger> {
public:
    void log(const std::string& message) {
        std::lock_guard<std::mutex> lock(mutex);
        std::cout << "[LOG] " << message << std::endl;
    }

private:
    std::mutex mutex;
    friend class Singleton<Logger>;
    Logger() = default;
};

// 使用
Logger::getInstance().log("System started");

2. 数据库连接池

c++ 复制代码
class ConnectionPool : public Singleton<ConnectionPool> {
public:
    Connection* getConnection() { /*...*/ }
    void releaseConnection(Connection* conn) { /*...*/ }

private:
    std::vector<Connection*> pool;
    friend class Singleton<ConnectionPool>;
    ConnectionPool() { /* 初始化连接池 */ }
};

最终实现推荐

c++ 复制代码
class MySingleton {
public:
    static MySingleton& getInstance() {
        static MySingleton instance;
        return instance;
    }

    // 禁用拷贝和移动
    MySingleton(const MySingleton&) = delete;
    MySingleton& operator=(const MySingleton&) = delete;
    MySingleton(MySingleton&&) = delete;
    MySingleton& operator=(MySingleton&&) = delete;

private:
    MySingleton() = default;  // 私有构造
    ~MySingleton() = default;
};
相关推荐
CoderYanger1 天前
动态规划算法-简单多状态dp问题:15.买卖股票的最佳时机含冷冻期
开发语言·算法·leetcode·动态规划·1024程序员节
CoderYanger1 天前
递归、搜索与回溯-FloodFill:33.太平洋大西洋水流问题
java·算法·leetcode·1024程序员节
CoderYanger1 天前
动态规划算法-斐波那契数列模型:2.三步问题
开发语言·算法·leetcode·面试·职场和发展·动态规划·1024程序员节
CoderYanger1 天前
动态规划算法-简单多状态dp问题:16.买卖股票的最佳时机含手续费
开发语言·算法·leetcode·动态规划·1024程序员节
CoderYanger1 天前
C.滑动窗口-求子数组个数-越短越合法——3258. 统计满足 K 约束的子字符串数量 I
java·开发语言·算法·leetcode·1024程序员节
CoderYanger1 天前
动态规划算法-路径问题:9.最小路径和
开发语言·算法·leetcode·动态规划·1024程序员节
CoderYanger1 天前
动态规划算法-路径问题:7.礼物的最大价值
开发语言·算法·leetcode·动态规划·1024程序员节
CoderYanger1 天前
动态规划算法-简单多状态dp问题:12.打家劫舍Ⅱ
开发语言·算法·leetcode·职场和发展·动态规划·1024程序员节
金融小师妹1 天前
机器学习驱动分析:ADP就业数据异常波动,AI模型预测12月降息概率达89%
大数据·人工智能·深度学习·编辑器·1024程序员节
CoderYanger1 天前
动态规划算法-简单多状态dp问题:18.买卖股票的最佳时机Ⅳ
开发语言·算法·leetcode·动态规划·1024程序员节