4.单例模式
-
定义
保证一个类仅有一个实例,并提供一个该实例的全局访问点。 -
解决了什么问题
稳定点:类只有一个实例,提供全局的访问点
变化点:如果多个类都是单例,能不能复用代码 -
代码结构
-
代码示例
// 版本一
class Singleton {
public:
static Singleton * GetInstance() {
if (_instance == nullptr) {
_instance = new Singleton();
}
return _instance;
}
private:
Singleton(){}; //构造
~Singleton(){};
Singleton(const Singleton &) = delete; //拷⻉构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
static Singleton * _instance;
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
// 有内存泄漏问题
// 版本二
class Singleton {
public:
static Singleton * GetInstance() {
if (_instance == nullptr) {
_instance = new Singleton();
atexit(Destructor);
}
return _instance;
}
private:
static void Destructor() {
if (nullptr != _instance) { //
delete _instance;
_instance = nullptr;
}
}
Singleton(){}; //构造
~Singleton(){};
Singleton(const Singleton &) = delete; //拷⻉构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
static Singleton * _instance;
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
// 还可以使⽤ 内部类,智能指针来解决; 此时还有线程安全问题
// 版本三
#include <mutex>
class Singleton { // 懒汉模式 lazy load
public:
static Singleton * GetInstance() {
// std::lock_guard<std::mutex>
lock(_mutex); // 3.1 切换线程
if (_instance == nullptr) {
std::lock_guard<std::mutex>
lock(_mutex); // 3.2
if (_instance == nullptr) {
_instance = new Singleton();
// 1. 分配内存
// 2. 调用构造函数
// 3. 返回指针
// 多线程环境下 cpu reorder操作
atexit(Destructor);
}
}
return _instance;
}
private:
static void Destructor() {
if (nullptr != _instance) {
delete _instance;
_instance = nullptr;
}
}
Singleton(){}; //构造
~Singleton(){};
Singleton(const Singleton &) = delete; //拷⻉构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
static Singleton * _instance;
static std::mutex _mutex;
};
Singleton* Singleton::_instance = nullptr;//静态成
员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化
// 版本4
// volitile
#include <mutex>
#include <atomic>
class Singleton {
public:
static Singleton * GetInstance() {
Singleton* tmp =
_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acqui
re);//获取内存屏障
if (tmp == nullptr) {
std::lock_guard<std::mutex>
lock(_mutex);
tmp =
_instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_relea
se);//释放内存屏障
_instance.store(tmp,
std::memory_order_relaxed);
atexit(Destructor);
}
}
return tmp;
}
private:
static void Destructor() {
Singleton* tmp =
_instance.load(std::memory_order_relaxed);
if (nullptr != tmp) {
delete tmp;
}
}
Singleton(){}; //构造
~Singleton(){};
Singleton(const Singleton &) = delete; //拷⻉
构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
static std::atomic<Singleton*> _instance;
static std::mutex _mutex;
};
std::atomic<Singleton*> Singleton::_instance;//静
态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化
// g++ Singleton.cpp -o singleton -std=c++11
// 版本5
class Singleton
{
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
private:
Singleton(){}; //构造
~Singleton(){};
Singleton(const Singleton &) = delete; //拷⻉
构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
};
// 继承 Singleton
// g++ Singleton.cpp -o singleton -std=c++11
/*该版本具备 版本5 所有优点:
1. 利⽤静态局部变量特性,延迟加载;
2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函
数;
3. 静态局部变量初始化时,没有 new 操作带来的cpu指令
reorder操作;
4. c++11 静态局部变量初始化时,具备线程安全;
*/
// 版本6
template<typename T>
class Singleton {
public:
static T& GetInstance() {
static T instance; // 这⾥要初始化
DesignPattern,需要调⽤DesignPattern 构造函数,同时会
调⽤⽗类的构造函数。
return instance;
}
protected:
virtual ~Singleton() {}
Singleton() {} // protected修饰构造函数,才能让
别⼈继承
private:
Singleton(const Singleton &) = delete; //拷⻉
构造
Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
Singleton(Singleton &&) = delete;//移动构造
Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
};
class DesignPattern : public
Singleton<DesignPattern> {
friend class Singleton<DesignPattern>; //
friend 能让Singleton<T> 访问到 DesignPattern构造函数
private:
DesignPattern() {}
~DesignPattern() {}
};
5.工厂模式
-
定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类 -
解决了什么问题
稳定点:创建同类对象的接口 同类对象有一个相同的职责
变化点:创建对象的扩展