一、简介
单例模式属于创建型模式,它提供一种创建对象的最佳方式。
单例模式的类,存在以下特点:
1、该类自己创建自己唯一的实例;
2、该类对外提供访问唯一实例的接口;
那么单例模式在什么场景适用,能够解决什么问题呢?
如果一个类的实例需要全局使用,并且不需要多个实例的时候,我们就需要为这个类使用单例模式。单例模式可以避免频繁地创建和销毁类对象,并且由于只有单实例,可以减少系统内存的使用。这些都是减少系统资源浪费,增加系统稳定性的优势。
二、怎么创建单例模式的类
首先,根据单例模式的特点,我们需要先明确单例模式需要什么
1)、为了保证类具有单实例,我们需要避免别的类对其实例化,所以需要对构造函数加以限制,使其只能类内构造;
2)、如果有必要,我们需要对单例的指针加锁保护,避免多线程的环境下,多次实例化的情况;
3)、需要准备外部能够获取这个唯一实例的接口,此接口需要定义为static类型,使其不需要依赖对象就可调用。
1、懒汉式
下面是C++参考代码
class SingleObject
{
public:
//单例对外接口,返回唯一单例对象
//声明为static,使其能够直接调用,不用从SingleObject调用
static SingleObject* GetInstance()
{
_mutex.lock();
if (nullptr == _instance)
{
_instance = new SingleObject();
}
_mutex.unlock();
return _instance;
}
void ShowMessage()
{
cout << "This is a single instance!" << endl;
}
private:
//构造函数
//构造函数需要声明为私有,以防止类外的实例化操作
SingleObject(){}
//不止默认构造函数,拷贝构造也需要显式地私有化,否则还是有在类外实例化地风险
SingleObject(const SingleObject& other){}
private:
//单例对象指针
//因为静态成员函数GetInstance需要访问_instance,所以_instance也要声明为静态的
//静态成员函数只能访问静态成员变量、其他静态成员函数和类外部的其他函数
static SingleObject* _instance;
//互斥锁
static std::mutex _mutex;
};
//静态成员变量需要类外初始化
SingleObject* SingleObject::_instance = nullptr;
std::mutex SingleObject::_mutex;
使用这个单例对象
int main()
{
SingleObject* object = SingleObject::GetInstance();
if (nullptr != object)
{
object->ShowMessage();
}
system("pause");
return 0;
}
上诉方式被称作“懒汉式”的单例创建方式
因为这个单实例只有外部第一次调用GetInstance的时候才会创建。
我们也可以在SingleObject类装载时,即_instance初始化的时候就进行实例化单例。这样可以不进行加所操作,因为类初始化只会进行一次。效率会比“懒汉式”更优,这种方式被称作“饿汉式”的创建方式。
饿汉式的缺点是可能会造成内存浪费,因为这个实例不一定会被使用。而且个人认为,一旦初始化的时候创建对象失败,后面没有时机进行二次创建。
2、饿汉式
参考代码
class SingleObject
{
public:
static SingleObject* GetInstance()
{
return _instance;
}
void ShowMessage()
{
cout << "This is a single instance!" << endl;
}
private:
SingleObject() {}
SingleObject(const SingleObject& other) {}
private:
static SingleObject* _instance;
};
//静态成员变量需要类外初始化,直接创建对象
SingleObject* SingleObject::_instance = new SingleObject();