(1·设计模式分类、单例)
设计模式
为了让代码更加模块化,降低耦合度,从而更易复用,扩展,组合,提高安全性,简化使用
分类
创建型模式: 指导如何更好的创建对象
结构型模式:指导如何将类和对象封装为较大的结构
行为型模式:指导如何让对象和类之间高效的沟通
单例模式
作用:保证一个类只有一个实例,并提供一个全局访问点来访问这个实例
1
2
3
4
5
6
7
8
9
10
11
12
class Singleton {
private:
// 私有的静态实例变量
static Singleton* instance = new Singleton();
// 私有的构造函数
Singleton() = default;
public:
// 公有的静态方法来获取实例
static Singleton* getInstance() {
return instance;
}
};
展开
饿汉:实例在类加载时就被创建,线程安全,浪费资源(如果从未使用该实例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton {
private:
// 私有的静态实例变量
static Singleton* instance;
// 私有的构造函数
Singleton() = default;
public:
// 公有的静态方法来获取实例
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
Singleton* Singleton::instance = nullptr;//类外定义
展开
懒汉模式:第一次使用时才创建,非线程安全(数据竞争),节省资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx; // 互斥锁
Singleton() = default;
public:
static Singleton* getInstance() {
if (instance == nullptr) { // 首次创建应加锁
std::lock_guard<std::mutex> lock(mtx); // 加锁,阻塞其他线程,lock_guard保证作用域结束自动unlock
if (instance == nullptr) { // 第二次检查(确保唯一)
instance = new Singleton();
}
}
return instance;
}
};
Singleton* Singleton::instance = nullptr;// 类外初始化
std::mutex Singleton::mtx;
展开
双重检查锁:在懒汉模式基础上,保证线程安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Singleton {
private:
// 私有构造函数,防止外部直接创建对象
Singleton() = default;
public:
// 静态成员函数,用于获取单例实例的引用
static Singleton& getInstance() {
// 静态局部变量,在首次调用该函数时初始化
static Singleton instance;
// 返回单例实例的引用
return instance;
}
};
展开
双重检查锁优化:使用局部静态变量,c++中如果在静态局部变量正在初始化时,有其他线程同时进入该变量的声明语句,那么这些并发执行的线程会等待初始化完成,因此不会数据竞争
实现方式:
- 私有的构造函数:防止外部代码创建类的实例,如果是public的,就可以创建多个类实例,这不符合目标
- 私有的静态实例变量:静态保证此对象在类的唯一性质,私有保证外部不能直接访问
- 公有的静态方法:静态保证可以不创建类实例就可以调用,公有保证外部可以直接访问
封装原则
你可能会疑惑上述的单例中为什么不直接暴露instance呢,而通过 public getInstance()去间接访问
封装原则:严格来说任何时候都不将成员变量设为 public,而通过两个接口读写
- get() 获取成员变量
- set() 设置成员变量
这样对外部隐藏内部实现细节,仅暴露必要的接口,提高安全性, 防止不正确的修改
本文由作者按照 CC BY 4.0 进行授权