前段时间我的学长推荐我去看一下设计模式,说这个对我做的项目会有很大的帮助,于是就开始了设计模式的学习,感觉设计模式有点枯燥乏味,如果不跟着讲解例子敲代码的话,说不定没多久我估计就睡了。
单例模式是最常用的设计模式,在应用程序的整个生命周期中,对象只有一个实例的时候,就会使用单例模式。简而言之,就是在代码的最开始到最后,这个类只能定义一个对象,无法定义第二个对象。在单例模式的定义过程中,有两点需要注意:
1、该类只允许存在一个实例。
2、需要为该单一实例提供一个全局访问点。
单一实例创建策略:通过限制构造函数(设置其为私有从而限制单例类的实例化)。之后在定义类时包含一个该类的静态私有对象,以便创建单例类的实例。
一、被动实例化
应用方法:
class Single
{
private:
static Single* instance;
Single(){};
public:
static Single getInstance()
{
if(instance == NULL)
{
instance = new Single();
}
return instance;
}
};
上述方法实现还是挺简单的,单例类由自身来维护一个对单一实例的静态引用,并由静态的getInstance()函数来返回该引用。单例模式创建单一实例的过程中使用到了一种叫做被动初始化的技术,其结果是直到第一次调用getInstance()函数时才会创建单一实例,这种技术保证单例类仅在需要时才会创建实例。
其实就是,在定义对象的时候,因为构造函数已经被设为私有的了,所以是无法访问构造函数的,这个时候就只能通过getInstance()函数来实现了,在getInstance()函数中就可以通过静态的对象instance来控制该类定义的次数了。
在在使用单例类的时候,一定要小心多个线程的影响,在单线程环境中,单例类会正常工作,而在多线程环境中,如果没有对获取实例的函数进行同步,就有可能创建多个实例。如果线程1刚进入if,还没有执行new语句,这个时候线程2也进入了if,这种情况下就会出现多个实例。可以用下面这个方法避免:
class Single
{
private:
static Single* instance;
Single(){};
public:
static Single getInstance()
{
if(instance == NULL)
{
pthread_mutex_lock(mutex);
if(instance == NULL)
{
instance = new Single();
}
pthread_mutex_unlock(mutex);
}
return instance;
}
};
完整代码:
#include <iostream>
#include <pthread.h>
using namespace std;
static pthread_mutex_t* mutex;
class Single;
class Single
{
private:
Single(){};
public:
static Single* instance;
static Single* getInstance()
{
if(instance == NULL)
{
pthread_mutex_lock(mutex);
if(instance == NULL)
{
instance = new Single();
}
pthread_mutex_unlock(mutex);
}
else
{
cout<<"资源已被占用"<<endl;
}
return instance;
}
void display()
{
cout<<"单例模式"<<endl;
}
};
Single* Single::instance = NULL;
int main()
{
pthread_mutex_init(mutex, NULL);
Single* sing = Single::getInstance();
sing->display();
Single* s = Single::getInstance();
s->display();
return 0;
}
二、主动实例化
除了上述的被动实例化之外,还可以用一个更加简洁的方法来实现相同的单例模式,但这会在加载类的时候实例化单例类。如下所示,可以实现主动实例化,同时也实现了对多线程的处理:
class Single
{
private:
static Single instance = new Single();
Single(){};
public:
static Single getInstance()
{
return instance;
}
};