单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。根据单例对象创建时间,可分为两种模式:懒汉模式和饿汉模式。
懒汉模式:延迟加载,不到万不得已不会去实例化类,也就是说第一次用到类实例的时候才会实例化。
#include <iostream>
#include <mutex>
using namespace::std;
// 懒汉模式一:多线程不安全
template <typename T>
class Singleton
{
public:
static T* getInstance()
{
if (instance_ == nullptr)
{
instance_ = new T();
}
return instance_;
}
private:
Singleton() = delete;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static T* instance_;
};
template <typename T>
T* Singleton<T>::instance_ = nullptr;
// 懒汉模式二:多线程安全
template <typename T>
class Singleton2
{
public:
static T* getInstance()
{
if (instance_ == nullptr)
{
mutex_.lock();
if (instance_ == nullptr)
{
instance_ = new T();
}
mutex_.unlock();
}
return instance_;
}
private:
Singleton2() = delete;
Singleton2(const Singleton2&) = delete;
Singleton2& operator=(const Singleton2&) = delete;
private:
static T* instance_;
static mutex mutex_;
};
template <typename T>
T* Singleton2<T>::instance_ = nullptr;
template <typename T>
mutex Singleton2<T>::mutex_;
class Printer
{
friend class Singleton<Printer>;
friend class Singleton2<Printer>;
private:
Printer() = default;
Printer(const Printer&) = delete;
Printer& operator=(const Printer&) = delete;
public:
void print() { cout << "Printer" << endl; }
};
int main(int argc, char* argv[])
{
Singleton<Printer>::getInstance()->print();
Singleton2<Printer>::getInstance()->print();
}
饿汉模式:在单例类定义的时候(即在main函数之前)就进行实例化。因为main函数执行之前,全局作用域的类成员变量instance_已经初始化,故没有多线程的问题。
#include <iostream>
#include <mutex>
using namespace::std;
// 饿汉模式
template <typename T>
class Singleton
{
private:
Singleton() = delete;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static T* getInstance()
{
return instance_;
}
private:
static T* instance_;
};
template <typename T>
T* Singleton<T>::instance_ = new T();
class Printer
{
friend class Singleton<Printer>;
private:
Printer() = default;
Printer(const Printer&) = delete;
Printer& operator=(const Printer&) = delete;
public:
void print() { cout << "Printer" << endl; }
};
int main(int argc, char* argv[])
{
Singleton<Printer>::getInstance()->print();
}