单件模式(单例模式)确保一个类只有一个实例,并提供一个全局访问点。
--《Head First设计模式》
单例模式三个特点:
- 保证全局只有一个类实例
- 该唯一实例只能由该类自行创建
- 必须向整个程序提供全局获取对象的访问点
单例模式优点:
- 全局只有一个该类的对象,节省了内存
- 避免重复生成和销毁类对象,提高了性能
- 唯一的类对象,保证了数据的正确性
使用场景
一般用于只允许全局唯一的情景,例如注册表,线程池,数据库连接类等,这既可以节省内存又能保证数据正确性。
C++单例模式几种写法:
1.“饿汉式”,顾名思义,实例化对象策略总是“迫不及待”的,也就是说不管整个程序是否真的有使用到对象,多会在程序开始时初始化。
“饿汉式”版本一,可能会造成内存泄露
//singleton.h
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
class Singleton
{
private:
Singleton();
~Singleton();
public:
static Singleton* getInstance();
void print();
private:
static Singleton* singleton;
};
#endif
//singleton.cc
#include "singleton.h"
#include <iostream>
Singleton::Singleton()
{
std::cout << "Singleton create!" << std::endl;
}
Singleton::~Singleton()
{
if (singleton)
delete singleton;
std::cout << "Singleton destory!" << std::endl;
}
Singleton* Singleton::getInstance()
{
return singleton;
}
void Singleton::print()
{
std::cout << "This is Singleton Pattern" << std::endl;
}
Singleton* Singleton::singleton = new Singleton();
客户使用:
#include "singleton.h"
#include <iostream>
using namespace std;
int main()
{
cout << "main..." << endl;
Singleton* singleton = Singleton::getInstance();
singleton->print();
return 0;
}
Linux下编译运行:
g++ -std=c++11 -o main main.cc singleton.cc
./main
上述的代码中存在内存泄露问题,因为singleton是用new显式生成的,如果要释放必定要显式调用delete。但是往往客户使用时会忘记,而且交由客户管理也不符合逻辑。
改进一:
添加delete方法
void Singleton::deleteSingleton()
{
if (singleton)
delete singleton;
}
#include "singleton.h"
#include <iostream>
using namespace std;
int main()
{
cout << "main..." << endl;
Singleton* singleton = Singleton::getInstance();
singleton->print();
singleton->deleteSingleton();
return 0;
}
改进二:
改进一中需要客户自己调用析构,也就是说交由客户管理,这不符合逻辑,改由静态变量(而非静态指针),让程序结束时自动释放。
//singleton.h
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
class Singleton
{
private:
Singleton();
~Singleton();
public:
static Singleton* getInstance();
void print();
void deleteSingleton();
private:
static Singleton singleton;
};
#endif
#include "singleton.h"
#include <iostream>
Singleton::Singleton()
{
std::cout << "Singleton create!" << std::endl;
}
Singleton::~Singleton()
{
std::cout << "Singleton destory!" << std::endl;
}
Singleton* Singleton::getInstance()
{
return &singleton;
}
void Singleton::print()
{
std::cout << "This is Singleton Pattern" << std::endl;
}
Singleton Singleton::singleton;
改进三:
如果非得用静态指针的方式,那么可以内嵌一个静态类进行管理。
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
class Singleton
{
private:
Singleton();
~Singleton();
public:
static Singleton* getInstance();
void print();
void deleteSingleton();
private:
static Singleton* singleton;
class SingletonGc
{
public:
~SingletonGc()
{
if (Singleton::singleton)
delete Singleton::singleton;
}
};
static SingletonGc gc;
};
#endif
Singleton* Singleton::singleton = new Singleton();
Singleton::SingletonGc Singleton::gc;
2.“懒汉式”,同样由名字可知,对象在需要的时候才会创建。
“懒汉式”版本一:(线程不安全,可能内存泄露)
//singleton.h
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
class Singleton
{
private:
Singleton();
~Singleton();
public:
static Singleton* getInstance();
void print();
void deleteSingleton();
private:
static Singleton* singleton;
};
#endif
#include "singleton.h"
#include <iostream>
Singleton::Singleton()
{
std::cout << "Singleton create!" << std::endl;
}
Singleton::~Singleton()
{
std::cout << "Singleton destory!" << std::endl;
}
Singleton* Singleton::getInstance()
{
if (singleton == NULL)
singleton = new Singleton();
return singleton;
}
void Singleton::print()
{
std::cout << "This is Singleton Pattern" << std::endl;
}
Singleton* Singleton::singleton = NULL;
内存泄露解决方案同上。
“懒汉式”版本二:(线程安全,效率低下)
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
#include <pthread.h>
class Singleton
{
private:
Singleton();
~Singleton();
public:
static Singleton* getInstance();
void print();
void deleteSingleton();
private:
static Singleton* singleton;
static pthread_mutex_t mutex;
};
#endif
#include "singleton.h"
#include <iostream>
#include <pthread.h>
Singleton::Singleton()
{
pthread_mutex_init(&mutex,NULL);
std::cout << "Singleton create!" << std::endl;
}
Singleton::~Singleton()
{
pthread_mutex_destroy(&mutex);
std::cout << "Singleton destroy!" << std::endl;
}
Singleton* Singleton::getInstance()
{
pthread_mutex_lock(&mutex);
if (singleton == NULL)
singleton = new Singleton();
pthread_mutex_unlock(&mutex);
return singleton;
}
void Singleton::print()
{
std::cout << "This is Singleton Pattern" << std::endl;
}
Singleton* Singleton::singleton = NULL;
pthread_mutex_t Singleton::mutex;
“懒汉式”版本三:(线程安全,效率高)
#include "singleton.h"
#include <iostream>
#include <pthread.h>
Singleton::Singleton()
{
pthread_mutex_init(&mutex,NULL);
std::cout << "Singleton create!" << std::endl;
}
Singleton::~Singleton()
{
pthread_mutex_destroy(&mutex);
std::cout << "Singleton destroy!" << std::endl;
}
Singleton* Singleton::getInstance()
{
if (singleton == NULL){
pthread_mutex_lock(&mutex);
if (singleton == NULL)
singleton = new Singleton();
pthread_mutex_unlock(&mutex);
}
return singleton;
}
void Singleton::print()
{
std::cout << "This is Singleton Pattern" << std::endl;
}
Singleton* Singleton::singleton = NULL;
pthread_mutex_t Singleton::mutex;