23种设计模式之——单例模式

时间:2022-09-09 08:32:45

 

单例模式也称为单件模式、单子模式。单例模式有许多种实现方法,甚至可以直接用一个全局变量做到这一点,但这样的代码显得很不优雅。《设计模式》一书中给出了一种很不错的实现。 

定义:确保一个类只有一个实例,而且自行实例化,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

类型:创建类模式

类图:

23种设计模式之——单例模式

 

单例模式应该是23种设计模式中最简单的一种模式了。它有以下几个要素:

  • 私有的构造方法
  • 指向自己实例的私有静态引用
  • 以自己实例为返回值的静态的公有的方法

        单例模式根据实例化对象时机的不同分为两种:一种是饿汉式单例,一种是懒汉式单例。饿汉式单例在单例类被加载时候,就实例化一个对象交给自己的引用;而懒汉式在调用取得实例方法的时候才会实例化对象。代码如下:

饿汉式单例

class CSingleton { 
public:
static CSingleton* getInstance(){
return m_pInstance;
}
private:
CSingleton(){}
static CSingleton* m_pInstance;
};
CSingleton* CSingleton::m_pInstance= new CSingleton;

懒汉式单例: 

 

class CSingleton { 
public:
static CSingleton* getInstance(){
if(m_pInstance == NULL){
m_pInstance = new CSingleton();
}
return m_pInstance;
}
private:
CSingleton(){}
static CSingleton* m_pInstance;
};
CSingleton* CSingleton::m_pInstance = NULL;

  单例模式需要注意的两个问题:

1.懒汉式单例模式线程安全问题:

  遇到多线程问题时,假如现在有两个线程A和线程B,线程A执行到 this.singletonPattern = new SingletonPattern(),正在申请内存分配,可能需要0.001微秒,就在这0.001微秒之内,线程B执行到if(this.singletonPattern == null),你说这个时候这个判断条件是true还是false?是true,那然后呢?线程B也往下走,于是乎就在内存中就有两个SingletonPattern的实例了,看看是不是出问题了?所以,在编写懒汉式单例模式时,应注意线程安全问题,具体方法视个人习惯而定。

2.资源回收:

  有经验的读者可能会问,m_pInstance指向的空间什么时候释放呢?我们知道,程序在结束的时候,系统会自动析构所有的全局变量。事实上,系统也会析构所有的类的静态成员变量,就像这些静态成员也是全局变量一样。

  利用这个特征,我们可以在单例类中定义一个这样的静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。如下面的代码中的CGarbo类(Garbo意为垃圾工人):

class CGarbo {      
public:
~CGarbo()
{
if (CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo;

  

 

单例模式的优点:

 

  • 在内存中只有一个对象,节省内存空间。
  • 避免频繁的创建销毁对象,可以提高性能。
  • 避免对共享资源的多重占用。
  • 可以全局访问。

 

适用场景:由于单例模式的以上优点,所以是编程中用的比较多的一种设计模式。我总结了一下我所知道的适合使用单例模式的场景:

 

  • 需要频繁实例化然后销毁的对象。
  • 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  • 有状态的工具类对象。
  • 频繁访问数据库或文件的对象。
  • 以及其他我没用过的所有要求只有一个对象的场景。

 

  至此为止,不考虑线安全问题,完整的单例模式代码如下:

饿汉式单例完整代码
class CSingleton { 
public:
static CSingleton* getInstance(){
return m_pInstance;
}
private:
CSingleton(){}
static CSingleton* m_pInstance;
class CGarbo {
public:
~CGarbo()
{
if (CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo;
};
CSingleton* CSingleton::m_pInstance= new CSingleton;
懒汉式单例完整代码 
class CSingleton { 
public:
static CSingleton* getInstance(){
if(m_pInstance == NULL){
m_pInstance = new CSingleton();
}
return m_pInstance;
}
private:
CSingleton(){}
static CSingleton* m_pInstance;
class CGarbo {
public:
~CGarbo()
{
if (CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo;
};
CSingleton* CSingleton::m_pInstance = NULL;