单例模式
设计模式中最简单,最常用的一种模式,这种模式用来保证某一个类的对象实例在应用中只有一个,即只被创建一次。
例如: 配置文件,日志对象,线程池,缓存等。
这些实例为了保证一致性,在整个应用中只需要被创建一次,例如,如果日志对象被创建多次,那么很可能日志中的内容就不一致,还有就是有时候占用资源过多的一些对象被创建多次会浪费资源,比如线程池等。
所以为了保证对象的单例,出现了单例模式。
步骤
-
将构造函数声明为私有
因为在创建一个对象的时候会去调用类的构造函数来完成对对象内存空间的分配以及成员的初始化,所以如果想限制对象的创建,首先应该禁止外界对象对构造函数的调用,通过这个办法就可以限制对象的创建。 -
在类中声明一个私有的静态的类的对象(实例)
这个实例就是我们需要获得的,唯一的实例。
之所以是static类型的是因为我们需要通过类直接获得而不通过对象获得,因为我们无法创建一个对象。
同时从封装的角度,我们下面需要定义一个static类型的接口用来返回这个实例。 -
定义一个static类型的public类型的事例获取函数
可以通过类直接调用这个函数获得类中定义的那个实例
饿汉模式
在类加载的时候已经创建好了类的实例,我们通过使用接口直接获得这个实例
- 饿汉是在类加载的时候就已经完成了类的实例化,所以在加载的时候会被比较慢,但运行起来比较快,而且是线程安全的。
class Singleton
{
private:
Singleton() {} //将构造函数定义为私有的,避免直接创建外部对象。
~Singleton()
{
delete sig;
}
static Singleton *sig; //声明一个私有的静态数据成员sig用来作为为一个实例。
public:
static Singleton *getInstance() //声明一个static类型的接口获得实例
{
return sig;
}
};
Singleton* Singleton::sig = new Singleton; //在类外进行实例的定义和初始化
懒汉模式
懒汉模式在类中只给出实例的声明并未给出定义。所以是当多个线程去竞争的时候是线程不安全的,所以需要使用锁机制
class Singleton2
{
private:
Singleton2() {}
static Singleton2 *sig; //只给出声明
public:
static Singleton2* getInstance();
};
Singleton2* Singleton2::getInstance()
{
if (sig == NULL)
{
sig = new Singleton2;
}
return sig;
}
Singleton2* Singleton2::sig; //不初始化,和饿汉模式的区别。
线程安全的懒汉模式
class Singleton
{
private:
Singleton() {} //将构造函数定义为私有的,避免直接创建外部对象。
static Singleton *sig; //声明一个私有的静态数据成员sig用来作为为一个实例。
public:
static Singleton *getInstance() //声明一个static类型的接口获得实例
{
if (sig == NULL)//双重检测锁
{
lock();
if (sig == NULL)
{
sig = new Singleton;
}
unlock();
}
return sig;
}
};
Singleton* Singleton::sig;// = new Singleton; //在类外进行实例的定义和初始化
网友评论