设计模式之单例模式
时间:2020-08-19 00:47:26
手机看文章
扫描二维码
随时随地手机看文章
[导读]程序喵最近开始系统学习回顾设计模式,希望能把学到的东西分享给大家,今天总结下创建型模式中最经典的单例模式。 “ 什 么 是 单 例 模 式 ? ” 这里首先介绍下什么是创建型模式,创建型模式主要解决对象的创建过程,封装对象复杂的创建过程,解耦对象
程序喵最近开始系统学习回顾设计模式,希望能把学到的东西分享给大家,今天总结下创建型模式中最经典的单例模式。
而单例模式指的就是在系统里一个类只能产生一个实例,确保全局唯一。
“
懒 汉 式 实 现 1
”
class Singleton {
public:
static Singleton *GetInstance();
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部构造对象,想拿到类的实例只能通过GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton *instance_;
static std::mutex mutex_;
};
Singleton *Singleton::instance_ = nullptr;
std::mutex Singleton::mutex_;
Singleton *Singleton::GetInstance() {
// double check
if (instance_ == nullptr) { // 1
std::unique_lock<std::mutex> lock(mutex_);
if (instance_ == nullptr) { // 2
instance_ = new Singleton();
}
}
return instance_;
}
int main() {
Singleton::GetInstance()->Func();
return 0;
}
为什么需要加锁?加锁的原因很简单,为了确保线程安全。
您看过代码可能也有些疑惑,明明加一次锁和第二次的判断就足够了,为什么在加锁之前还需要进行一次判断呢?这里可以考虑只需要在判断指针为空的时候才去加锁,避免每次调用方法时都加锁,可以减少加锁解锁带来的额外开销。
这里需要将类的构造函数和拷贝构造函数等设成私有函数,避免外部构造类的实例,防止外部通过new关键字进行实例化。
“
懒 汉 式 实 现 2
”
class Singleton {
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部构造对象,想拿到类的实例只能通过GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
int main() {
Singleton::GetInstance().Func();
return 0;
}
“
饿 汉 式 实 现
”
class Singleton {
public:
static Singleton *GetInstance();
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部构造对象,想拿到类的实例只能通过GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton *instance_;
};
Singleton *Singleton::instance_ = new Singleton();
Singleton *Singleton::GetInstance() {
return instance_;
}
int main() {
Singleton::GetInstance()->Func();
return 0;
}
“
std::call_once实现 ”
template <typename T>
class SingleTon {
public:
static T& instance() {
std::call_once(once_, &SingleTon::init);
return *value_;
}
private:
SingleTon();
~SingleTon();
SingleTon(const SingleTon&) = delete;
SingleTon& operator=(const SingleTon&) = delete;
static void init() { value_ = new T(); }
static T* value_;
static std::once_flag once_;
};
总结
-
类只能有一个实例。 -
外部用户不能也无法自行对类进行实例化,实例化的操作需要类内部去实现。 -
整个进程共用一个类的实例,且需要是线程安全的。
往期推荐
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!