参考:《大话设计模式》《Thinking In C++ 》第二卷。
传说中的四人帮Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides ,介绍了24中设计模式,在此就不一一列举,其中单例模式可以算的上其中最简单的一个,现在我们就将其详细做一下探讨。
单例模式主要讲解的是一个类有且只有一个对象。而单例模式又被分成了饿汉和懒汉模式。饿汉模式主要指自己被加载时就创建了对象。懒汉模式主要指在第一次引用时才会将自己实例化。饿汉模式要求提前占用系统资源,而懒汉模式有会面临着多线程访问临界资源的问题需要加锁来加以限制。所以到底采用哪种根据情况而定,当需要创建的实例较小且不总需要时建议采用懒汉模式。
//懒汉模式实现
class Singleton
{
private:
static Singleton *Instance; //私有保证其不会被被单独调用(静态成员不一定需要对象来访问)静态保证其只有一个副本。
Singleton(){} //构造函数私有保证其不能创建对象,虽然可以什么都没有但必须存在
public:
static Singleton*Getinstance() //提供一个公共访问接口
{
if(Instance==NULL)
Instance = new Singleton(); //如果为NULL才创建体现懒汉,且保证只有一个
return Instance;
}
};
Singleton* Singleton::Instance =NULL;
上述程序中已经单例模式的基本构造解释清楚。下面看一下饿汉模式。
class Singleton{
private:
static Singleton instance; //一开始就创建
int i;
Singleton(int x):i(x){}
public:
static Singleton Getinstance()
{
return instance;
}
};
Singleton Singleton::instance(4);
下面看一下多线程的访问:
多线程的方位我们以懒汉模式来说明(参考成《大话设计模式》)解决多线程模式我们一般采用锁机制。
下面看一个例子:
上面可能有人会说为什么不直接给instance加锁,这个主要你不知道加锁时其有没有,它有可能为空。但是这样每次调用时都要,加锁导致开销较大,所以我们继续优化。
我们只是在判定不为空时再加锁,这种方法称为Double-Check Locking(双重锁定)
这样我们再来分析,有些人可能认为外面已经为空了则里面没必要在判断了其实不然。当两个线程都走到了第一个if内部如果一个先执行,另一个则等带,如果里面没有if判断则两个线程都认为空,这样就会产生两个对象,但是如果里面有if则不会出现这个问题。
这篇博客我会继续改进,欢迎各位大神指正。