单例(Singleton)模式

单例模式

单例模式旨在同一程序中,某个类只存在一个实例。解决此类问题的主要思想在于生成全局对象,本质是通过其在内存中位置不同,完成生存周期,及可见域的限制。使其存在与全局作用域,通过编译器来防止多个对象产生。

在面向对象中,我们通过singleton来完成对某的对向的单例化。

实现原则:

1. 私有构造函数,与拷贝构造
2. 静态实例引用(静态变量或静态指针)
3. Instance()接口
4. 通过类型的全局能力来在用编译器限制第二个singleton的产生。

分为懒汉模式和饿汉模式

懒汉式

实例通过类静态成员直接在类外初始化。从程序启动到程序终止一直存在。程序简单, 不好处在于,生存周期长,不可动态创建和销毁。

注意: 单例模式的重点在于内存中只有一个实例,我们并不关注程序中有多少个变量。因此, 我们不对拷贝构造进行私有化控制。

单例(Singleton)模式

饿汉式

主要应用在实例的生存周期补丁,需要动态创建,动态销毁的状态。两次判断原因: 第一次判断为第一次创建与以后的创建做区别,减少了加锁的次数。
第二次判断为加锁后,防止多次new对象实例,做到了可重入。

单例(Singleton)模式

//singleton.hpp

#include <mutex>
#include <string>
#include <iostream>

#ifndef _DESIGN_PATTERN_SINGLETON_PATTERN_SINGLETON_
#define _DESIGN_PATTERN_SINGLETON_PATTERN_SINGLETON_

namespace design_pattern
{
/**
 * lazy mode
 */
template <typename Ty>
class SingletonLazy
{
private:
	SingletonLazy() {}
	static Ty instance_;

public:
	static Ty * Instance()
	{
		return &instance_;
	}

};

template <typename Ty>
Ty SingletonLazy<Ty>::instance_;

/**
 * hungry mode
 */
template <typename Ty>
class SingletonHungry
{
private:
	SingletonHungry() {}
	static Ty *pinstance_;

public:
	static Ty *Instance()
	{
		if (nullptr == pinstance_)
		{
			std::mutex mtx;
			mtx.lock();
			if (nullptr == pinstance_)
				pinstance_ = new Ty;
			mtx.unlock();
		}
		return pinstance_;
	}

};
template <typename Ty>
Ty * SingletonHungry<Ty>::pinstance_ = nullptr;
}


#endif //!_DESIGN_PATTERN_SINGLETON_PATTERN_SINGLETON_

//singleton_main.cpp

#include <iostream>
#include <string>
#include <thread>
#include "sigleton.hpp"
using namespace design_pattern;
using std::thread;
using std::string;
using std::cout;
using std::endl;


void GetInstance()
{
	cout << "Lazy mode<string>:" << SingletonHungry<string>::Instance() << endl;
	cout << "Hungry mode<int>:" << SingletonLazy<int>::Instance() << endl;
}

int main()
{
	thread thd1(GetInstance);
	thread thd2(GetInstance);

	thd1.join();
	thd2.join();

	return 0;
}

懒汉式的推广

由懒汉式我们容易想到,只要内存区域具有全局性,获得实例的路径唯一,就可完成简单的对象单例化。

在linux的errno中,全局变量errno, oom机制中的oom_handle,使用静态局部变量,使用函数作为获得实例的路径。具有一定的封装性。缺少OO特性。

template <typename Ty>
Ty *InstanceHandle()
{
	static Ty instance;
	return &instance;
}

语法tips

  • c++ 11 thread
    1. 构造
    2. join
    3. detach
    4. get_id
    5. joinable
    6. tative_handle
    7. operator=
    8. swap
  • 函数内可以临时定义类型