赞
踩
笔记参照内容来自尚硅谷的《Java设计模式课程》,GOF的《设计模式》和《大话设计模式》等资料,之后实现C++版本。
饿汉式(静态常量)应用实例:
1.构造器私有化(防止类被调用new操作);
2.类的内部创建对象;
3.向外暴露一个静态的公共方法;getInstance();
//饿汉式单例模式 #include <iostream> class Singleton { public: static Singleton* getInstance() { return single; } private: Singleton() { } static Singleton* single; }; //类内的静态变量 在类外初始化,并且初始化加类型,但是不添加static关键字,和普通的静态变量以做区分 Singleton* Singleton::single=new Singleton(); int main() { Singleton* single1=Singleton::getInstance(); Singleton* single2=Singleton::getInstance(); std::cout<<"single1 address:"<<single1<<std::endl; std::cout<<"single1 address:"<<single2<<std::endl; }
优缺点:这种单例模式可用,但是可能造成内存浪费(因为无论类有没有被加载,静态变量均在main函数执行之前就执行了初始化)
在调用getInstance()函数的时候,才对静态变量进行实例化;
这样可以避免饿汉式的内存浪费
//线程不安全 懒汉式 单例模式 #include <iostream> #include <thread> class Singleton { public: static Singleton* getInstance() { if (single==nullptr) { single=new Singleton(); std::cout<<"single address:"<<single<<std::endl; } return single; } private: Singleton() {} static Singleton* single; }; Singleton* Singleton::single=nullptr; int main() { Singleton* single1=Singleton::getInstance(); Singleton* single2=Singleton::getInstance(); std::cout<<"single1 address:"<<single1<<std::endl; std::cout<<"single2 address:"<<single2<<std::endl; }
缺点:在多线程情况下,无法做到线程安全,可能导致创建多个类的实例,从而使得单例模式失效;
在创建时,进行加锁操作,实现线程同步,从而保证线程安全性;
//线程安全 懒汉式 单例模式 #include <iostream> #include <thread> #include <mutex> class Singleton { public: static Singleton* getInstance() { std::lock_guard<std::mutex> guard(m_mutex); if (single==nullptr) { single=new Singleton(); std::cout<<"single address:"<<single<<std::endl; } return single; } private: Singleton() {} static Singleton* single; static std::mutex m_mutex; }; Singleton* Singleton::single=nullptr; std::mutex Singleton::m_mutex; #include <pthread.h> int main() { Singleton* single1=Singleton::getInstance(); Singleton* single2=Singleton::getInstance(); // std::thread th1(&Singleton::getInstance); // th1.join(); std::cout<<"single1 address:"<<single1<<std::endl; std::cout<<"single2 address:"<<single2<<std::endl; }
缺点:执行效率比较低,
作为单例模式,单例最少在使用第一次的时候已经创建好,直接返回即可,而现在的方式每次都需要进行加锁操作;
对线程安全的懒汉式进行改进;
主要改进方法:1.缩小锁的范围,这种方法使得在线程的单例不为空时,直接返回,而不会使用到锁;
2.同时,如果线程单例为空,又会加锁,保证线程安全;
//线程安全 懒汉式 单例模式 #include <iostream> #include <thread> #include <mutex> class Singleton { public: static Singleton* getInstance() { if (single==nullptr) { std::lock_guard<std::mutex> guard(m_mutex); if (single==nullptr) { single=new Singleton(); } // std::cout<<"single address:"<<single<<std::endl; } return single; } private: Singleton() {} static Singleton* single; static std::mutex m_mutex; }; //原来java版本中 包含了关键字 volatile Singleton* Singleton::single=nullptr; std::mutex Singleton::m_mutex; #include <pthread.h> int main() { Singleton* single1=Singleton::getInstance(); Singleton* single2=Singleton::getInstance(); std::thread th1(&Singleton::getInstance); th1.join(); std::cout<<"single1 address:"<<single1<<std::endl; std::cout<<"single2 address:"<<single2<<std::endl; }
推荐在多线程环境中使用。
C++无法通过类内的成员类实现懒汉的效果;
经过调试,类内的静态成员变量在main()之前就已经加载完毕;
#include <iostream> #include <mutex> class Singleton { public: static Singleton* getInstance() { std::lock_guard<std::mutex> guard(s_mutex); return SingletonInstance::instance; } private: class SingletonInstance { public: static Singleton* instance; }; static std::mutex s_mutex; }; std::mutex Singleton::s_mutex; //java中的静态变量可以直接在类内进行初始化 而C++不行,所以不一定能起到饿汉的效果 //经过调试C++起不到懒汉的效果,因为类内静态变量在main函数执行之前就被加载了 Singleton* Singleton::SingletonInstance::instance=new Singleton(); int main() { Singleton* single1=Singleton::getInstance(); Singleton* single2=Singleton::getInstance(); Singleton* single3=Singleton::getInstance(); std::cout<<"single1:"<<single1<<std::endl; std::cout<<"single2:"<<single2<<std::endl; std::cout<<"single3:"<<single3<<std::endl; }
#include <iostream> #include <mutex> #include <string> template <typename T> class Singleton { public: static T* getInstance() { if (m_val==nullptr){ std::lock_guard<std::mutex> guard(m_mutex); if (m_val==nullptr){ m_val=new T; } } return m_val; } private: static T* m_val; static std::mutex m_mutex; }; template <typename T> T* Singleton<T>::m_val=nullptr; template <typename T> std::mutex Singleton<T>::m_mutex; class Student { public: Student():m_num(0),m_name("") {} Student(int num, const std::string& name):m_num(num),m_name(name) {} int num() const {return m_num;} std::string name() const {return m_name;} void setNum(int num) {m_num=num;} void setName(const std::string& name) {m_name=name;} void printInfo() { std::cout<<"num:"<<m_num<<"\t"<<"name:"<<m_name<<std::endl; } private: int m_num; std::string m_name; }; int main() { Student* student=Singleton<Student>::getInstance(); student->setNum(100); student->setName("daniel"); Student* stu1=Singleton<Student>::getInstance(); stu1->printInfo(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。