单例模式设计到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
意图:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
主要解决:一个全局使用的类频繁地创建于销毁。
何时使用:控制实例数目,节省系统资源的时候。
如何解决:判断系统时候已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
实例:1、一个班级只有一个班主任。
2、一些设备管理器设计为单例模式,
优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
2、避免对资源的多重占用。
缺点:没有接口,不能继承,与单一职责原则冲突。
使用场景:1、要求生产唯一序列号。
2、创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。
C++代码实现:
1、懒汉式是使用到时才实例化对象,在调用到getInstance()方法时才会new出一个单例对象。
可能会带来的问题:
#include<iostream> #include<memory> #include<mutex> using namespace std; //创建懒汉单例类 class SingleObject { public: typedef shared_ptr<SingleObject> ptr; ~SingleObject() { cout << "析构函数~!~!" << endl; } //C++11 关键字delete 表民绝对禁止使用拷贝构造函数 SingleObject(SingleObject&) = delete; SingleObject& operator=(const SingleObject&) = delete; static SingleObject* getInstance() { if (instance == nullptr) { instance = new SingleObject; } return instance; } private: SingleObject() { cout << "构造函数~!~!" << endl; } static SingleObject* instance; }; //类的数据成员不能在类的声明体中初始化 //必须在类外进行初始化 SingleObject* SingleObject::instance = nullptr; int main() { SingleObject* ins = SingleObject::getInstance(); SingleObject* ins_2 = SingleObject::getInstance(); //SingleObject* ins_3 = new SingleObject; //编译无法通过 system("pause"); return 0; }
1、线程安全问题:在多线程环境下,假设存在两个线程同时调用到getInstance()方法。第一个线程判断isnstance==nullptr,于是实例化单例;此时第二个线程判断isnstance==nullptr,于是也开始实例化单例。这样就不能保证单例的唯一性。
解决办法:加锁。
2、内存泄漏:类中只负责new出对象,却没有负责delete对象。析构函数中却没有被调用,所以会导致内存泄漏。
解决办法:使用共享指针(shared_ptr)。
为什么不在析构函数中调用delete?自己在思考:static成员函数中new出的对象可以在析构函数中delete吗?
2、线程安全、内存安全的懒汉单例模式
#include<iostream> #include<memory> #include<mutex> using namespace std; //创建线程安全、内存安全的懒汉类 class SingleObject { public: //为shared_ptr定义一个别名Ptr typedef shared_ptr<SingleObject> Ptr; ~SingleObject() { cout << "析构函数~!~!" << endl; } //C++11 关键字delete 表民绝对禁止使用拷贝构造函数 SingleObject(SingleObject&) = delete; SingleObject& operator=(const SingleObject&) = delete; static Ptr getInstance() { if (instance == nullptr) { //互斥锁 lock_guard<mutex> lk(m_mutex); if (instance == nullptr) { instance = shared_ptr<SingleObject>(new SingleObject); //instance = Ptr(new SingleObject); 和上面相同 } } return instance; } private: SingleObject() { cout << "构造函数~!~!" << endl; } static Ptr instance; static mutex m_mutex; }; //类的数据成员不能在类的声明体中初始化 //必须在类外进行初始化 SingleObject::Ptr SingleObject::instance = nullptr; mutex SingleObject::m_mutex; int main() { SingleObject::Ptr ins = SingleObject::getInstance(); SingleObject::Ptr ins_2 = SingleObject::getInstance(); system("pause"); return 0; }
3、懒汉单例--局部静态变量
#include<iostream> using namespace std; class SingleObject { public: ~SingleObject() { cout << "析构函数~!~!" << endl; } //C++11 关键字delete 表民绝对禁止使用拷贝构造函数 SingleObject(SingleObject&) = delete; SingleObject& operator=(const SingleObject&) = delete; static SingleObject& getInstance() { static SingleObject instance; return instance; } private: SingleObject() { cout << "构造函数~!~!" << endl; } }; //类的数据成员不能在类的声明体中初始化 //必须在类外进行初始化 int main() { SingleObject& ins = SingleObject::getInstance(); system("pause"); return 0; }