单例模式可以说是最普为人知的一种设计模式了吧,但单例模式的细节又有多少人想清了呢?
那就先提几个问吧
单例模式的对象该如何释放?何时释放?如何优雅的释放?
单例模式有哪几种实现方式?
如果你瞬间就一大段代码涌出脑海,我建议你别看这篇博文了,省得浪费你时间。
那下面就开始说正事吧
UML图
饿汉式
时间换取空间的实现方式,打死我也不创建对象。这种模式只有在第一个对象实例化的时候才会创建对象,但实现起来稍微麻烦一些,要考虑到多线程的场景。
hungry_singleton_mode.h
#ifndef _SINGLETON_
#define _SINGLETON_
#include "string"
#include "iostream"
using namespace std;
class myself
{
private:
static myself *m_me;
static pthread_mutex_t mutex;
string m_attribuate;
myself(string attr)
{
m_attribuate = attr;
}
//嵌套类实现自释放单例对象
class clean_up
{
public:
~clean_up()
{
if (m_me != NULL)
{
cout << "myself distruction." << endl;
delete m_me;
m_me = NULL;
}
}
};
static clean_up m_clean;
public:
static myself* get_instance(string attr)
{
//直接加锁性能不佳
if (m_me == NULL)
{
pthread_mutex_lock(&mutex);
if (m_me == NULL)
{
m_me = new myself(attr);
}
pthread_mutex_unlock(&mutex);
}
return m_me;
}
string show_attr()
{
return m_attribuate;
}
};
#endif
hungry_singleton_mode.cpp
#include "iostream"
#include "pthread.h"
#include "hungry_singleton_mode.h"
using namespace std;
pthread_mutex_t myself::mutex = PTHREAD_MUTEX_INITIALIZER;
myself* myself::m_me = NULL; //饿汉式
myself::clean_up myself::m_clean; //初始化构造内部类对象
int main(int argc, char const *argv[])
{
myself *p_me = myself::get_instance("I'm a lonely gambler.");
myself *p_me2 = myself::get_instance("my English is poor.");
cout << p_me->show_attr() << endl;
cout << p_me2->show_attr() << endl;
return 0;
}
输出结果
懒汉式
空间换时间的方法,一开始初始化的时候便创建对象,所以不用考虑多线程场景下线程同步的问题,故实现相对较简单。
#include <iostream>
using namespace std;
class myself
{
private:
static myself* m_me;
string m_attr;
myself(string attr)
{
m_attr = attr;
}
class clean_up
{
public:
~clean_up()
{
if (m_me != NULL)
{
cout << "myself destruction." << endl;
delete m_me;
m_me = NULL;
}
}
};
static clean_up m_clean;
public:
static myself* get_instance()
{
return m_me;
}
string show_attr()
{
return m_attr;
}
};
myself* myself::m_me = new myself("hello world.");
myself::clean_up myself::m_clean;
int main(int argc, char const *argv[])
{
myself *p_me = myself::get_instance();
cout << p_me->show_attr() << endl;
return 0;
}
输出结果
单例模式的对象如何优雅的释放
通过内部类的形式实现单例模式的对象自动释放,具体代码如上。但是切记内部类的对象开始需要初始化。