单例设计模式
- 应用场景
- 特点
- 设计模式分类
- 懒汉设计模式
- 饿汉设计模式
- 使用
- 编写的测试代码
- 运行结果
应用场景
当多个类都需要调用某一个类的一些公共接口,同时不想创建多个该类的对象,可以考虑将该类封装为一个单例模式。
特点
单例模式的特点:
1.只有一个单例对象。因而构造函数需要私有化,不能被外界访问。同时也不能进行对象的拷贝和赋值操作,故而也需要将拷贝构造函数和赋值运算符重载函数删除或者私有。
2.提供对外获取实例对象的公共访问接口。其它类可以通过这个接口获取单例对象。
设计模式分类
单例模式可以分为懒汉模式和饿汉模式。
所谓懒汉模式,就是当程序运行过程中需要单例对象的时候再创建。
所谓饿汉模式,就是定义类的时候就创建单例对象。
懒汉设计模式
1.懒汉设计模式下的单例模式,如果项目很简单,不需要考虑多线程的问题,可以这样编写懒汉模式下的单例模式。
class Singleton
{
private:
Singleton()=default;
Singleton(const Singleton&)=delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance()
{
if (m_pInstance == nullptr)
{
m_pInstance = new Singleton;
}
return m_pInstance;
}
private:
static Singleton *m_pInstance;
static mutex m_mutex;
};
Singleton *Singleton::m_pInstance = nullptr;
mutex Singleton::m_mutex;
2.下面是懒汉设计模式下的单例模式示例,这里考虑多线程,故而引入双重检查锁来保护单例对象的创建,是线程安全的。
class Singleton
{
private:
Singleton()=default;
Singleton(const Singleton&)=delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance()
{//双重检查锁定
if (m_pInstance == nullptr)//注意这里的判断条件
{
lock_guard<mutex> locker(m_mutex);//注意这里的参数
if (m_pInstance == nullptr)
{
m_pInstance = new Singleton;
}
}
return m_pInstance;
}
private:
static Singleton *m_pInstance;
static mutex m_mutex;
};
Singleton *Singleton::m_pInstance = nullptr;
mutex Singleton::m_mutex;
3.还可以在支持C++11的编译器基础之上,使用static创建懒汉模式下的单例对象。(并发程序中会等待变量初始化完成)也是线程安全的。
class Singleton
{
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton &) = delete;
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;//注意返回的指针,若返回变量对象,会调用拷贝构造函数出现错误
}
};
饿汉设计模式
这里提供两种编写的方式,但无论哪种,都是先创建实例对象。
1.以指针的形式创建对象。
class Singleton
{
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance()
{
return m_pInstance;
}
private:
static Singleton *m_pInstance;
};
Singleton* Singleton::m_pInstance = new Singleton;
2.以对象的方式创建。
class Singleton
{
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance()
{
return &m_instance;
}
private:
static Singleton m_instance;
};
Singleton Singleton::m_instance;
使用
编写的测试代码
这里创建两次单例对象,输出对象的地址,看看是否是同一个实例。
Singleton *p1 = Singleton::getInstance();
Singleton *p2 = Singleton::getInstance();
cout << "p1:" << p1 << " p2:" << p2 << endl;
运行结果
注意:本文没有给出编程过程中实际需要的头文件,测试代码也只给出用于测试的部分。