引言
在现实生活中,有许许多多的职位,是有且仅有一个人能任职的,以确保这个职位是独一无二的。在程序中,也有很多类需要进行"计划生育",比如Windows系统的回收站,以及很多游戏里面的独一无二的一些BOSS或者成就、称号之类的。今天的单例设计模式就是在做这么一件事。
简单介绍
单例设计模式的作用在于让某个类仅产生一个实例对象,且提供该对象的功能接口给使用者。它有多种实现方法,但最核心的思想不外乎三点:
(1)构造函数私有化
(2)获取接口静态公开化
(3)唯一实例静态私有化
这里讲解一下这三点的作用:
(1)让外部使用者不能够产生额外的实例对象
(2)由于外部不能产生额外的实例对象,因此不能在获取到实例对象之前,访问到类的任何接口,而调用static方法不需要产生实例,所有需要提供一个公共的static方法来让用户获取实例对象(或产生实例对象并返回)。
(3)私有化使得外部只能通过static方法来获取实例对象,静态化的主要目的是方便该实例的初始化。
只要做到以上三点,能够达到外部只能获取一个实例对象的目的,就可以说实现了单例模式,简单的单例UML图如下所示:
话不多说,上测试代码。
单例类的定义
懒汉式单例,即在使用时才产生实例对象,相关代码如下:
//三要素 构造函数私有化 获取接口静态公开化 唯一实例静态私有化
class Singleton1;
using Ptr = shared_ptr<Singleton1>;
//懒汉式 线程不安全 需要加锁
class Singleton1 {
private:
Singleton1() {};
Singleton1(Singleton1& s) = delete;
Singleton1& operator=(Singleton1& s) = delete;
public:
void Play()
{
cout << "Singleton1.Playing................." << endl;
}
static Ptr getInstance() {
if (!Instance)
{
lock_guard<mutex>auto_lock(m_mutex);
if (!Instance)
{
Instance = shared_ptr<Singleton1>(new Singleton1);
}
}
return Instance;
}
private:
static Ptr Instance;
static mutex m_mutex;
};
饿汉式单例,即定义好类就直接产生实例对象,相关代码如下:
//饿汉式
class Singleton2 {
public:
~Singleton2() {
std::cout << "Singleton - destructor." << std::endl;
}
static Singleton2* getInstance() {
return m_instance;
}
void use() const {
std::cout << "Singleton2 - in use." << std::endl;
}
private:
Singleton2() {}
Singleton2(Singleton2&) = delete;
Singleton2& operator=(const Singleton2&) = delete;
static Singleton2* m_instance;
};
全部代码如下:
#include<iostream>
#include<string>
#include<mutex>
#include<memory>
using namespace std;
//三要素 构造函数私有化 获取接口公开静态化 唯一实例静态私有化
class Singleton1;
using Ptr = shared_ptr<Singleton1>;
//懒汉式 线程不安全 需要加锁
class Singleton1 {
private:
Singleton1() {};
Singleton1(Singleton1& s) = delete;
Singleton1& operator=(Singleton1& s) = delete;
public:
void Play()
{
cout << "Singleton1.Playing................." << endl;
}
static Ptr getInstance() {
if (!Instance)
{
lock_guard<mutex>auto_lock(m_mutex);
if (!Instance)
{
Instance = shared_ptr<Singleton1>(new Singleton1);
}
}
return Instance;
}
private:
static Ptr Instance;
static mutex m_mutex;
};
//初始化静态成员
Ptr Singleton1::Instance = nullptr;
mutex Singleton1::m_mutex;
//饿汉式
class Singleton2 {
public:
~Singleton2() {
std::cout << "Singleton - destructor." << std::endl;
}
static Singleton2* getInstance() {
return m_instance;
}
void use() const {
std::cout << "Singleton2 - in use." << std::endl;
}
private:
Singleton2() {}
Singleton2(Singleton2&) = delete;
Singleton2& operator=(const Singleton2&) = delete;
static Singleton2* m_instance;
};
//直接new
Singleton2* Singleton2::m_instance = new Singleton2();
int main()
{
Ptr singleton1 = Singleton1::getInstance();
singleton1->Play();
Singleton2* s = Singleton2::getInstance();
s->use();
system("pause");
return 0;
}
对于单例模式的实现,还有许多反式,不管怎样实现,其中心思想依旧是上面所讲的三点。预告:下节将讲述抽象工厂模式。