简介
单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
特点
1.单例类只能有一个实例。
2.单例类必须自己创建自己的唯一实例。
3.单例类必须给所有其他对象提供这一实例。
非模板实现方式
1.内部类+静态对象实现
#include <iostream>
using namespace std;
// 单例模式1:内部类+静态对象实现
// 单例类
class Singleton
{
private:
class AutoRelease
{
public:
AutoRelease(){ cout << "AutoRelease()" << endl; }
~AutoRelease()
{
if(m_pInstance != nullptr)
{
cout << "~AutoRelease()" << endl;
delete m_pInstance;
}
}
};
public:
// 获取对象
// 在多线程下是非线程安全的,如果想要线程安全,则需要加锁
static Singleton* getInstance()
{
if(nullptr == m_pInstance)
{
m_pInstance = new Singleton();
}
return m_pInstance;
}
private:
Singleton() {cout << "Singleton()" << endl;}
~Singleton() {cout << "~Singleton()" << endl;}
static Singleton* m_pInstance;
static AutoRelease m_auto;
};
// 当用到单例模式时,对象才初始化,称之为饿汉模式(懒汉模式,懒加载)。优点:节省空间,缺点:需要加锁,浪费效率。
Singleton* Singleton::m_pInstance = nullptr;
// 在进入main函数之前就创建在堆空间里面,所以是线程安全的,又称饱汉模式。优点:节省效率,缺点:浪费堆空间。
/* Singleton* Singleton::m_pInstance = getInstance(); */
Singleton::AutoRelease Singleton::m_auto;
int main()
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
cout << "p1 = " << p1 << endl;
cout << "p2 = " << p2 << endl;
return 0;
}
2.atexit+pthread_once实现
#include <iostream>
#include <stdlib.h> //使用函数atexit
#include <pthread.h> //使用线程函数
using namespace std;
// 单例模式2:atexit + pthread_once
// ps:只能在Linux环境下,因为关联了POSIX的线程库
// 单例类
class Singleton
{
public:
// 获取对象
// 在多线程下是非线程安全的,如果想要线程安全,则需要加锁
static Singleton* getInstance()
{
pthread_once(&m_once, init);
return m_pInstance;
}
static void init()
{
m_pInstance = new Singleton();
atexit(destory);
}
static void destory()
{
if(m_pInstance != nullptr)
{
delete m_pInstance;
}
}
private:
Singleton() {cout << "Singleton()" << endl;}
~Singleton() {cout << "~Singleton()" << endl;}
static Singleton* m_pInstance;
static pthread_once_t m_once;
};
// 当用到单例模式时,对象才初始化,称之为饿汉模式(懒汉模式,懒加载)。优点:节省空间,缺点:需要加锁,浪费效率。
Singleton* Singleton::m_pInstance = nullptr;
pthread_once_t Singleton::m_once = PTHREAD_ONCE_INIT;
// 在进入main函数之前就创建在堆空间里面,所以是线程安全的,又称饱汉模式。优点:节省效率,缺点:浪费堆空间。
/* Singleton* Singleton::m_pInstance = getInstance(); */
int main()
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
cout << "p1 = " << p1 << endl;
cout << "p2 = " << p2 << endl;
return 0;
}
模板实现方式
1.内部类+静态对象实现
#include <iostream>
using namespace std;
template <typename Type>
class Singleton
{
private:
class AutoRelease
{
public:
AutoRelease(){cout << "AutoRelease()" << endl;}
~AutoRelease()
{
if(m_pInstance != nullptr)
{
delete m_pInstance;
m_pInstance = nullptr;
cout << "~AutoRelease()" << endl;
}
}
};
public:
template<typename... Args>//Args:模板参数包
static Type* getInstance(Args... args)//args:函数参数包
{
if(m_pInstance == nullptr)
{
//模板只会在实例化之后,才会进行参数推导
//所以要调用一次m_auto
m_auto;
m_pInstance = new Type(args...);//解函数参数包
}
return m_pInstance;
}
private:
Singleton();
~Singleton();
private:
static Type* m_pInstance;
static AutoRelease m_auto;
};
template<typename Type>
Type* Singleton<Type>::m_pInstance = nullptr;
template<typename Type>
//这里在最前面需要加class是因为无法确定AutoRelease是成员变量还是嵌套类还是成员函数
//所以显式声明为class
class Singleton<Type>::AutoRelease Singleton<Type>::m_auto;
//demo------------------------------------
class Point
{
public:
Point(int x = 0, int y = 0)
:m_x(x)
,m_y(y)
{cout << "Point(int x, int y)" << endl;}
~Point(){cout << "~Point()"<< endl;}
friend ostream & operator<<(ostream & os, const Point & rhs);
private:
int m_x;
int m_y;
};
ostream & operator<<(ostream & os, const Point & rhs)
{
os << "(" << rhs.m_x << ", " << rhs.m_y << ")";
return os;
}
int main()
{
Point* pt1 = Singleton<Point>::getInstance(1, 2);
Point* pt2 = Singleton<Point>::getInstance(1, 2);
cout << static_cast<Point*>(pt1) << endl;
cout << static_cast<Point*>(pt2) << endl;
cout << "*pt1 = " << *pt1 << endl;
cout << "*pt2 = " << *pt2 << endl;
return 0;
}
2.pthread_once实现
#include <iostream>
#include <pthread.h>
using namespace std;
class Noncopyable
{
protected:
Noncopyable() = default;
~Noncopyable() = default;
private:
Noncopyable(const Noncopyable&) = delete;
const Noncopyable& operator=( const Noncopyable& ) = delete;
};
template <typename Type>
class Singleton : Noncopyable
{
public:
static Type* getInstance()
{
pthread_once(&m_once, init);
return m_pInstance;
}
static void init()
{
m_pInstance = new Type();
}
private:
Singleton();
~Singleton();
private:
static Type* m_pInstance;
static pthread_once_t m_once;
};
template<typename Type>
Type* Singleton<Type>::m_pInstance = nullptr;
template<typename Type>
pthread_once_t Singleton<Type>::m_once = PTHREAD_ONCE_INIT;
//demo------------------------------------
class Point
{
public:
Point(){cout << "Point()" << endl;}
~Point(){cout << "~Point()"<< endl;}
void init(int x, int y)
{
m_x = x;
m_y = y;
cout << "Point::init()" << endl;
}
friend ostream & operator<<(ostream & os, const Point & rhs);
private:
int m_x;
int m_y;
};
ostream & operator<<(ostream & os, const Point & rhs)
{
os << "(" << rhs.m_x << ", " << rhs.m_y << ")";
return os;
}
int main()
{
Point* pt1 = Singleton<Point>::getInstance();
Point* pt2 = Singleton<Point>::getInstance();
pt1->init(1,2);
pt2->init(2,4);
cout << static_cast<Point*>(pt1) << endl;
cout << static_cast<Point*>(pt2) << endl;
cout << "*pt1 = " << *pt1 << endl;
cout << "*pt2 = " << *pt2 << endl;
return 0;
}