单例模式定义:
一种对象创建型模式, 使用单例模式, 可以保证为一个类只生成唯一的实例对象。 也就是说, 在整个程序空间中, 该类只存在一个实例对象。
从结构图可以看出,构造函数是私有的。
为什么需要单例模式:
1、在多个线程之间,比如初始化一次socket资源
2、在整个程序空间使用全局变量,共享资源
3、大规模系统中,为了性能的考虑,需要节省对象的创建时间
实现步骤:
1、构造函数私有化
2、提供一个全局的静态方法(全局访问点)
3、在类中定义一个静态指针,指向本类的变量的静态变量指针
单例模式分类及实现:
懒汉式:
懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,很懒的,配置文件的实例直到用到的时候才会加载。
#include <iostream>
using namespace std;
//懒汉式
class Singleton
{
private:
Singleton()
{
cout<<"Singleton"<<endl;//只会打印一次
}
public:
static Singleton* getInstance()
{
if(sin == NULL)//懒汉式: 1 每次获取实例都要判断 2 多线程会有问题
{
sin = new Singleton;
}
return sin;
}
static void deleteInstance()
{
if(sin != NULL)
{
delete sin;
sin = NULL;
}
}
private:
static Singleton * sin;//未初始化
};
// 静态变量在类的外部进行初始化
Singleton * Singleton::sin = NULL; //懒汉式 并没有创建单例对象
int main()
{
Singleton * p1 = Singleton::getInstance();
Singleton * p2 = Singleton::getInstance();
if(p1 == p2)
cout<<"same object"<<endl;
Singleton::deleteInstance();
return 0;
}
饿汉式:
饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。
#include <iostream>
using namespace std;
//饿汉式
class Singleton2
{
private:
Singleton2()
{
cout<<"Singleton2"<<endl;//只会打印一次
}
public:
static Singleton2* getInstance()//这里由于在全局变量中已经初始化了,直接返回
{
return sin;
}
static void deleteInstance()
{
if(sin != NULL)
{
delete sin;
sin = NULL;
}
}
private:
static Singleton2 * sin;//未初始化
};
// 静态变量在类的外部进行初始化
Singleton2 * Singleton2::sin = new Singleton2; //饿汉式,不管你创建不创建实例, 均实例化
//
int main()
{
Singleton2 * p1 = Singleton2::getInstance();
Singleton2 * p2 = Singleton2::getInstance();
if(p1 == p2)
cout<<"same object"<<endl;
Singleton2::deleteInstance();
return 0;
}
/*
饿汉式和懒汉式代码上最直接的区别就是饿汉式句柄生成时就已经分配好空间,而懒汉式则是在调用获取句柄的函数中才分配空间。
*/
懒汉式和饿汉式比较:
对于执行顺序,懒汉式是,全局静态变量创建——main函数——创建实例——构造函数——删除实例;
对于饿汉式有点不同,由于在全局静态变量就已经需要初始化,所以顺序是,全局静态变量创建——创建示例——构造函数——main函数——删除实例。(按照我的例子来说就是,饿汉式的main函数还没运行,已经打印“Singleton2"了)。