最近看了一些设计模式相关的问题,本着纸上得来终觉浅的目的,因而手撸了单例设计模式的懒汉模式和饿汉模式。
1 长话短说:
- 懒汉模式:对象在调用时再进行实例化,这样可以减少内存使用。
- 饿汉模式:对象在创建时立即进行实例化,虽然简单快速,但是存在浪费内存的可能性。
2 代码讲解
2.1 代码共同点:
- 默认构造函数、拷贝构造函数、赋值构造函数全部私用化,防止外部对其进行实例化。
- 实例化对象全部通过API接口获取,满足面向对象的封装特性。
2.2 代码异同点:
- 懒汉模式使用了线程锁(这里是互斥量),防止在多线程应用中,对象多次实例化。这部分可以参考多线程的知识。
- 懒汉模式中,instance初始化为nullptr;饿汉模式中,instance初始化为new SinglePattern_eager 对象。
// 懒汉模式
class SinglePattern_lazy {
private:
SinglePattern_lazy() {
cout << "SinglePattern_lazy contructor called !" << endl;
}
SinglePattern_lazy(const SinglePattern_lazy&) = delete;
SinglePattern_lazy& operator = (const SinglePattern_lazy&) = delete;
static SinglePattern_lazy *instance;
static mutex mtx;
public:
~SinglePattern_lazy() {
cout << "~SinglePattern_lazy decontructor called !" << endl;
}
static SinglePattern_lazy* getInstance() {
if (!instance) {
unique_lock<mutex> lock(mtx);
if (!instance) {
instance = new SinglePattern_lazy();
return instance;
}
}
return instance;
}
};
SinglePattern_lazy *SinglePattern_lazy::instance = nullptr;
mutex SinglePattern_lazy::mtx;
// 饿汉模式
class SinglePattern_eager {
private:
SinglePattern_eager() {
cout << "SinglePattern_eager contructor called !" << endl;
}
SinglePattern_eager(const SinglePattern_eager&) = delete;
SinglePattern_eager& operator = (const SinglePattern_eager&) = delete;
static SinglePattern_eager *instance;
public:
~SinglePattern_eager() {
cout << "~SinglePattern_eager decontructor called !" << endl;
}
static SinglePattern_eager* getInstance() {
return instance;
}
};
SinglePattern_eager *SinglePattern_eager::instance = new SinglePattern_eager();
// 测试的主程序
int main() {
SinglePattern_lazy* p5 = SinglePattern_lazy::getInstance();
SinglePattern_lazy* p6 = SinglePattern_lazy::getInstance();
SinglePattern_eager* p7 = SinglePattern_eager::getInstance();
SinglePattern_eager* p8 = SinglePattern_eager::getInstance();
return 0;
}
// 编译指令
Linux平台、g++ 11.3.0
g++ singlepattern.cpp -o singlepattern
// 运行代码及结果
$ ./singlepattern
SinglePattern_eager contructor called !
SinglePattern_lazy contructor called !
从结果看,构造函数均被调用一次,即产生一个实例化对象。