单例模式

打印 上一主题 下一主题

主题 1037|帖子 1037|积分 3111


一、要点

0.单例模式,顾名思义只能有一个实例对象
1.私有化构造函数:不能随便调用构造函数来实例化对象
2.删除拷贝构造函数、赋值运算符函数:确保唯一实例
3.利用静态成员变量,存储指向单例对象的指针:静态方法属于类,不属于具体的实例对象。
4.提供静态方法,在堆上获取单例对象

二、代码

耽误实例化、懒加载、懒汉式:实例在第一次利用时才会被创建

1.核心代码

  1. static Singleton* getInstance() {
  2.     if (instance == nullptr) {
  3.         instance = new Singleton();  // 只有在第一次调用时创建实例
  4.     }
  5.     return instance;
  6. }
复制代码

2.具体注释代码

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. //单例模式:要通过给的接口来创造唯一实例。
  5. //因此,要将构造函数私有化,并且删除拷贝构造和赋值运算符函数
  6. class Singleton
  7. {
  8. public:
  9.     //静态方法,用于获取唯一的实例。静态方法属于类,而非实例对象
  10.     //懒加载、懒汉式、延迟实例化
  11.     static Singleton* getInstance()
  12.     {
  13.         if(pInstance == nullptr){
  14.             pInstance = new Singleton();
  15.         }
  16.         return pInstance;
  17.     }
  18.     void display()
  19.     {
  20.         cout << "This is the Singleton instance." << "\n";
  21.     }
  22. private:
  23.     //构造函数私有化,防止外部创建对象
  24.     Singleton()
  25.     {
  26.         cout << "Singleton instance created.\n";
  27.     }
  28.     //禁用拷贝构造和赋值运算符函数
  29.     Singleton(const Singleton & ) = delete;
  30.     Singleton & operator=(const Singleton &) = delete;
  31.     //静态成员变量,存储唯一的实例
  32.     static Singleton* pInstance;
  33. };
  34. //类外初始化静态成员变量
  35. Singleton* Singleton::pInstance = nullptr;
  36. int main()
  37. {
  38.     //获取单例对象的唯一实例
  39.     Singleton* s1 = Singleton::getInstance();
  40.     s1->display();
  41.     //再次获取单例对象的实例
  42.     Singleton* s2 = Singleton::getInstance();
  43.     s2->display();
  44.     //验证两个指针是否指向同一个实例
  45.     if(s1 == s2){
  46.         cout << "Both pointer point to the same instance.\n";
  47.     }
  48.     return 0;
  49. }
复制代码
另一版
  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. //单例模式:要通过给的接口来创造唯一实例。
  5. //因此,要将构造函数私有化,并且删除拷贝构造和赋值运算符函数
  6. class Singleton
  7. {
  8. private:
  9.     //构造函数私有化,防止外部创建对象
  10.     Singleton()
  11.     {
  12.         cout << "Singleton instance created.\n";
  13.     }
  14.     //禁用拷贝构造和赋值运算符函数
  15.     Singleton(const Singleton & ) = delete;
  16.     Singleton & operator=(const Singleton &) = delete;
  17.     //静态成员变量,存储唯一的实例
  18.     static Singleton* instance;
  19. public:
  20.     //静态方法,用于获取唯一的实例
  21.     static Singleton* getInstance()
  22.     {
  23.         if(instance == nullptr){
  24.             instance = new Singleton(); //延迟实例化
  25.         }
  26.         return instance;
  27.     }
  28.     void display()
  29.     {
  30.         cout << "This is the Singleton instance." << "\n";
  31.     }
  32. };
  33. //静态成员变量初始化为nullptr
  34. Singleton* Singleton::instance = nullptr;
  35. int main()
  36. {
  37.     //获取单例对象的唯一实例
  38.     Singleton* s1 = Singleton::getInstance();
  39.     s1->display();
  40.     //再次获取单例对象的实例
  41.     Singleton* s2 = Singleton::getInstance();
  42.     s2->display();
  43.     //验证两个指针是否指向同一个实例
  44.     if(s1 == s2){
  45.         cout << "Both pointer point to the same instance.\n";
  46.     }
  47.     return 0;
  48. }
复制代码

3.无注释代码 (单线程时,存在线程安全问题)

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. class Singleton
  5. {
  6. public:
  7.     static Singleton* getInstance()
  8.     {
  9.         if(pInstance == nullptr){
  10.             pInstance = new Singleton();
  11.         }
  12.         return pInstance;
  13.     }
  14. private:
  15.     Singleton(){};
  16.     Singleton(const Singleton & rhs) = delete;
  17.     Singleton & operator= (const Singleton & rhs) = delete;
  18.     static Singleton* pInstance;
  19. };
  20. Singleton* Singleton::pInstance = nullptr;
  21. int main()
  22. {
  23.     Singleton* s1 = Singleton::getInstance();
  24.     Singleton* s2 = Singleton::getInstance();
  25.     if(s1 == s2){
  26.         cout << "s1 == s2,是单例的\n";
  27.     }else{
  28.         cout << "s1 != s2,不是单例的\n";
  29.     }
  30.     return 0;
  31. }
复制代码

4.思量线程安全 (getInstance加锁)

  1. #include <iostream>
  2. #include <mutex>
  3. using std::cout;
  4. using std::mutex;
  5. using std::lock_guard;
  6. class Singleton
  7. {
  8. public:
  9.     static Singleton* getInstance()
  10.     {
  11.         lock_guard<mutex> lock(mtx);
  12.         if(pInstance == nullptr){
  13.             pInstance = new Singleton();
  14.         }
  15.         return pInstance;
  16.     }
  17. private:
  18.     Singleton(){};
  19.     Singleton(const Singleton & rhs) = delete;
  20.     Singleton & operator= (const Singleton & rhs) = delete;
  21.     static Singleton* pInstance;
  22.     static mutex mtx; //互斥锁,确保线程安全
  23. };
  24. Singleton* Singleton::pInstance = nullptr;
  25. mutex Singleton::mtx;
  26. int main()
  27. {
  28.     Singleton* s1 = Singleton::getInstance();
  29.     Singleton* s2 = Singleton::getInstance();
  30.     if(s1 == s2){
  31.         cout << "s1 == s2,是单例的\n";
  32.     }else{
  33.         cout << "s1 != s2,不是单例的\n";
  34.     }
  35.     return 0;
  36. }
复制代码

4.1 进一步减少加锁的开销,利用双重查抄锁

  1. // 线程安全的 getInstance 方法,使用双重检查锁
  2. static Singleton* getInstance()
  3. {
  4.     if(pInstance == nullptr) {  // 第一次检查,无锁
  5.         std::lock_guard<std::mutex> lock(mtx);  // 加锁
  6.         if(pInstance == nullptr) {  // 第二次检查,加锁后
  7.             pInstance = new Singleton();
  8.         }
  9.     }
  10.     return pInstance;
  11. }
复制代码

5.开释单例资源以避免内存泄露(智能指针)

  1. #include <iostream>
  2. #include <mutex>
  3. #include <memory>
  4. using std::cout;
  5. using std::mutex;
  6. using std::lock_guard;
  7. using std::unique_ptr;
  8. class Singleton
  9. {
  10. public:
  11.     static Singleton* getInstance()
  12.     {
  13.         lock_guard<mutex> lock(mtx);
  14.         if(pInstance == nullptr){
  15.             /* pInstance = new Singleton(); */
  16.             pInstance = unique_ptr<Singleton>(new Singleton());
  17.         }
  18.         return pInstance.get();
  19.     }
  20. private:
  21.     Singleton(){};
  22.     Singleton(const Singleton & rhs) = delete;
  23.     Singleton & operator= (const Singleton & rhs) = delete;
  24.     /* static Singleton* pInstance; */
  25.     static unique_ptr<Singleton> pInstance;
  26.     static mutex mtx; //互斥锁,确保线程安全
  27. };
  28. /* Singleton* Singleton::pInstance = nullptr; */
  29. unique_ptr<Singleton> Singleton::pInstance = nullptr;
  30. mutex Singleton::mtx;
  31. int main()
  32. {
  33.     Singleton* s1 = Singleton::getInstance();
  34.     Singleton* s2 = Singleton::getInstance();
  35.     if(s1 == s2){
  36.         cout << "s1 == s2,是单例的\n";
  37.     }else{
  38.         cout << "s1 != s2,不是单例的\n";
  39.     }
  40.     return 0;
  41. }
复制代码

6.饿汉式

饿汉式:在类加载时就举行实例化
  1. #include <iostream>
  2. using namespace std;
  3. class Singleton{
  4. public:
  5.     // 提供全局访问点
  6.     static Singleton& getInstance()
  7.     {
  8.         // 静态局部变量在程序启动时初始化
  9.         static Singleton instance;
  10.         return instance;
  11.     }
  12.     // 删除拷贝构造函数和赋值操作符,防止复制
  13.     Singleton(const Singleton&) = delete;
  14.     Singleton& operator=(const Singleton&) = delete;
  15.     // 示例方法
  16.     void display() const{
  17.         cout << "Singleton::display() called on instance: " << this << endl;
  18.     }
  19. private:
  20.     // 私有构造函数
  21.     Singleton(){
  22.         cout << "Singleton()" << endl;
  23.     }
  24.     // 私有析构函数
  25.     ~Singleton(){
  26.         cout << "~Singleton()" << endl;
  27.     }
  28. };
  29. int main()
  30. {
  31.     // 通过getInstance获取单例对象的引用,并调用示例方法
  32.     Singleton& s1 = Singleton::getInstance();
  33.     s1.display();
  34.     // 再次获取单例对象的引用,验证它们是同一个实例
  35.     Singleton& s2 = Singleton::getInstance();
  36.     s2.display();
  37.     // 输出将展示s1和s2有相同的地址,说明它们是同一个实例
  38.     return 0;
  39. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

石小疯

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表