概念
单例模式表示只允许存在唯一对象实例
graph LR;
S(单例模式)
subgraph T[特点]
A(禁止在类外部创建对象)
B(类自己内部维护唯一对象)
C(提供访问该对象方法)
end
subgraph R[措施]
A1(私有化构造函数)
B1(静态成员变量)
C1(静态成员函数)
end
S-->A-->A1
S-->B-->B1
S-->C-->C1
graph LR;
X(分类)
X-->A(饿汉式)-->A1(无论用不用单例对象, 程序启动即创建)
X-->B(懒汉式)-->B1(单例对象用时再创建, 不用即销毁)
实现
静态变量, 确保在多个调用中保持相同内存地址, 只有在第一次调用时才会分配内存
C
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int value;
} Singleton;
Singleton* GetInstance() {
static Singleton* s = NULL;
if (s == NULL) {
s = (Singleton*)malloc(sizeof(Singleton));
s->value = 0;
}
return s;
}
int main() {
Singleton* s1 = GetInstance();
Singleton* s2 = GetInstance();
printf("s1 address: %p\n", s1);
printf("s2 address: %p\n", s2);
return 0;
}
C++
#include <iostream>
class Singleton {
public:
// 返回单例, C++11 以上线程安全
static Singleton& GetInstance() {
static Singleton s;
return s;
}
// 禁用拷贝构造函数
Singleton(Singleton const&) = delete;
// 禁用赋值构造函数
Singleton& operator=(Singleton const&) = delete;
private:
// 构造与析构函数设置为私有类型
Singleton() = default;
~Singleton() = default;
};
int main(void) {
Singleton& s1 = Singleton::GetInstance();
Singleton& s2 = Singleton::GetInstance();
Singleton& s3 = Singleton::GetInstance();
std::cout << &s1 << std::endl;
std::cout << &s2 << std::endl;
std::cout << &s3 << std::endl;
return 0;
}
可发现仅执行了一次构造与析构函数, 并且创建出对象地址均一致, 说明为同个对象
单例模板
#include <iostream>
template <typename T>
class Singleton {
public:
static T& GetInstance() {
static T s;
return s;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
protected:
Singleton() = default;
virtual ~Singleton() = default;
};
// 派生类
class Log : public Singleton<Log> {
// 为使父类能访问派生类构造与析构函数
friend class Singleton<Log>;
public:
Log(const Log&) = delete;
Log& operator=(const Log&) = delete;
private:
Log() = default;
~Log() = default;
};