C++完美实现Singleton模式
- 格式:pdf
- 大小:133.95 KB
- 文档页数:10
c++设计模式:单件模式(SingletonPattern)定义:单件模式确保⼀个类只有⼀个实例,并提供⼀个全局访问点实现⼀:#include <iostream>using namespace std;class CSingleton{public:static CSingleton* getInstance();static void cleanInstance();int getValue();void setValue(int iValue);private:int m_iValue;static CSingleton* m_pSingleton;CSingleton();~CSingleton();};CSingleton* CSingleton::m_pSingleton = NULL;CSingleton::CSingleton(){cout << "Constructor" << endl;}CSingleton::~CSingleton(){cout << "Destructor" << endl;}CSingleton* CSingleton::getInstance(){if (NULL == m_pSingleton){m_pSingleton = new CSingleton();}return m_pSingleton;}void CSingleton::cleanInstance(){delete m_pSingleton;}int CSingleton::getValue(){return m_iValue;}void CSingleton::setValue(int iValue){m_iValue = iValue;}int main(){CSingleton* pSingleton1 = CSingleton::getInstance();CSingleton* pSingleton2 = CSingleton::getInstance();pSingleton1->setValue(123);if (pSingleton1->getValue() == pSingleton2->getValue()){cout << "Two objects is the same instance" << endl;}else{cout << "Two objects isn't the same instance" << endl;}CSingleton::cleanInstance();return0;}相信⼤多数的同仁都喜欢使⽤上边这种单件模式的实现⽅法,如果在单线程的情况下,是没有问题的,但如果是多线程,那么就极有可能会返回两个不同的对象,在调⽤CSingleton::getInstance的时候,两个线程如果都同时运⾏完if判断,⽽⼜还没有调⽤到构造函数的话,想象下后果吧。
⽤C++实现单例模式⼏种写法这篇⽂章主要介绍了C++实现单例模式实例详解的相关资料,需要的朋友可以参考下设计模式之单例模式C++实现⼀、经典实现(⾮线程安全)class Singleton{public:static Singleton* getInstance();protected:Singleton(){}private:static Singleton *p;};Singleton* Singleton::p = NULL;Singleton* Singleton::getInstance(){if (NULL == p)p = new Singleton();return p;}⼆、懒汉模式与饿汉模式懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第⼀次⽤到类实例的时候才会去实例化,所以上边的经典⽅法被归为懒汉实现;饿汉:饿了肯定要饥不择⾷。
所以在单例类定义的时候就进⾏实例化。
特点与选择由于要进⾏线程同步,所以在访问量⽐较⼤,或者可能访问的线程⽐较多时,采⽤饿汉实现,可以实现更好的性能。
这是以空间换时间。
在访问量较⼩时,采⽤懒汉实现。
这是以时间换空间。
线程安全的懒汉模式1.加锁实现线程安全的懒汉模式class Singleton{public:static pthread_mutex_t mutex;static Singleton* getInstance();protected:Singleton(){pthread_mutex_init(&mutex);}private:static Singleton* p;};pthread_mutex_t Singleton::mutex;Singleton* Singleton::p = NULL;Singleton* Singleton::getInstance(){if (NULL == p){pthread_mutex_lock(&mutex);if (NULL == p)p = new Singleton();pthread_mutex_unlock(&mutex);}return p;}class Singleton{public:static pthread_mutex_t mutex;static Singleton* getInstance();protected:Singleton(){pthread_mutex_init(&mutex);}};pthread_mutex_t Singleton::mutex;Singleton* Singleton::getInstance(){pthread_mutex_lock(&mutex);static singleton obj;pthread_mutex_unlock(&mutex);return &obj;}饿汉模式(本⾝就线程安全)class Singleton{public:static Singleton* getInstance();protected:Singleton(){}private:static Singleton* p;};Singleton* Singleton::p = new Singleton; Singleton* Singleton::getInstance(){ return p;}。
单例模式(C++代码实现)1、先来谈谈什么是单例模式这个单例模式说⽩了就⼀个句话:我是皇帝我独苗看看书上的定义:单例模式(Singleton Pattern)Ensure a class has only one instance, and provide a global point of access to it.(确保⼀个类只有⼀个实例,⽽且⾃⾏实例化并向整个系统提供这个实例)使⽤场景:⼀个系统要求⼀个类只有且仅有⼀个对象,如果出现多个对象就会出现不良反应,可以采⽤单例模式要求⽣成唯⼀序列号在整个项⽬需要⼀个共享访问点或共享数据创建⼀个对象需要消耗的资源过多,如需要访问IO和数据库等资源需要⼤量定义静态常量和静态⽅法(如⼯具类)的环境,当然也可以直接定义为static2、实现思路:既然只能有⼀个实例,那我这个类⾥的构造函数就不能被随便调⽤了,那我就把构造函数写成私有的,这样别⼈就不能调⽤了,接下来就该考虑我⾃⼰这个独苗该怎么产⽣了,定义⾥⾯说到⾃⾏实例化,并且提供给整个系统,那我就⽤⼀个static 实例化⼀个实例,然后返回这个static实例。
3、考虑的问题⼀个实例,整个系统使⽤,那线程同步问题就必须要考虑了。
为了解决这个问题:懒汉模式、饿懒汉模式、Meyers Singleton(⽬前最推荐的C++单例写法)4、代码实现//Meyers Singleton(⽬前最推荐的C++单例写法)#include <iostream>using namespace std;class Singleton{public:static Singleton& Instance(){static Singleton theSingleton;return theSingleton;}void doSomeThong();private:Singleton();~Singleton();};Singleton::Singleton(){}Singleton::~Singleton(){}void Singleton::doSomeThong(){cout << "单例类" << endl;cout << "C++最推荐的单例类写法" << endl;}int main(){Singleton::Instance().doSomeThong();return0;}//懒汉模式:顾名思义,是⼀种典型的拖延(lazy)策略。
.NETc#单体模式(Singleton)单体模式(Singleton)是经常为了保证应⽤程序操作某⼀全局对象,让其保持⼀致⽽产⽣的对象,例如对⽂件的读写操作的锁定,数据库操作的时候的事务回滚,还有任务管理器操作,都是⼀单体模式读取的。
创建⼀个单体模式类,必须符合三个条件:1:私有构造函数(防⽌其他对象创建实例);2:⼀个单体类型的私有变量;3:静态全局获取接⼝下⾯我写⼀个类,为了看是不是单体,就加了⼀个计数器,如果是同⼀个类,那么这个类的计数每次调⽤以后就应该⾃动加⼀,⽽不是重新建对象归零:.NET c# 单体模式using System;using System.Threading;public class Singleton{private int ObjCount=0;private Singleton(){Console.WriteLine("创建对象");}private static Singleton objInstance = null;public static Singleton getInstance() {if (objInstance==null) objInstance=new Singleton();return objInstance;}public void ShowCount(){ObjCount++;Console.WriteLine("单个对象被调⽤了{0}次",ObjCount);}};然后我们来测试⼀下:public class ConsoleTest{public static void Main(string[] args){Console.WriteLine("开始执⾏单体模式");for(int i=0;i<5;i++){Singleton.getInstance().ShowCount();}Console.ReadLine();}};我在这个Main⾥⾯执⾏了5次,看看输出的结果:开始执⾏单体模式创建对象单个对象被调⽤了1次单个对象被调⽤了2次单个对象被调⽤了3次单个对象被调⽤了4次单个对象被调⽤了5次在这⾥可以看出,每次都是使⽤的同⼀个对象,实现了单体。
C++ 单件类singleton 模式与示例在写MANET Simulator 时,为了记录trace 文件,我用了一个LogFile 的类,这个类为了使用简便,而不必在每个使用日志的类中都建立一个LogFile对象,最好的办法就是把这个LogFile类设计成Singleton.具体如下:1)--------------------------------------- 头文件:#ifndef _LOG_H_#define _LOG_H_#include <iostream>#include <fstream>class LogFile{private:LogFile();~LogFile();LogFile( const LogFile& ); // Prevent copy-construction.public:static LogFile* instance();private:static LogFile* pObjLog;void CloseFiles();public:// 1 Error log file, record the errors and warnings.static std::ofstream m_ofErrLog;// 2 Running log file, record the running results and hints.static std::ofstream m_ofRunLog;// 3 Forwarding log file, record the forwarding actions.static std::ofstream m_ofForwardLog;// 4 Location log file, record the nodes' moving actions and locations.static std::ofstream m_ofLocLog;// 5 MN's SIR_state log file, record the MN' SIR states.static std::ofstream m_ofSIRLog;// 6 Record the Percolation Probability of all MNs.static std::ofstream m_ofPPLog;};#endif2)--------------------------------------- cpp文件:#include "..\Log\Log.h"std::ofstream LogFile::m_ofErrLog("NS_ErrLog.txt");std::ofstream LogFile::m_ofRunLog("NS_RunLog.txt");std::ofstream LogFile::m_ofForwardLog("NS_ForwardingLog.txt"); std::ofstream LogFile::m_ofLocLog("NS_LocationLog.txt");std::ofstream LogFile::m_ofSIRLog("NS_SIRLog.txt");std::ofstream LogFile::m_ofPPLog( "Trace\\PercoPr.tr", std::ios::app ); LogFile* LogFile::pObjLog = new LogFile();LogFile::LogFile(){}LogFile::~LogFile(){CloseFiles();if ( NULL != pObjLog ){delete pObjLog;pObjLog = NULL;}}LogFile* LogFile::instance(){if ( NULL != pObjLog ){return pObjLog;}return NULL;}void LogFile::CloseFiles(){m_ofErrLog.close();m_ofRunLog.close();m_ofForwardLog.close();m_ofLocLog.close();m_ofSIRLog.close();m_ofPPLog.close();}这样,只要包含了头文件,就可以在其他地方使用静态trace文件记录trace信息了,如: LogFile::instance()->m_ofErrLog << "Error: the simulate time can not be negative.\n";或LogFile::instance()->m_ofRunLog << "\n---- The NS begins running now. -----\n";整理至此,以便备忘。
C++11实现线程安全的单例模式1. 饿汉模式 使⽤饿汉模式实现单例是⼗分简单的,并且有效避免了线程安全问题,因为将该单例对象定义为static变量,程序启动即将其构造完成了。
代码实现:class Singleton {public: static Singleton* GetInstance() { return singleton_; }static void DestreyInstance() { if (singleton_ != NULL) { delete singleton_; }}private: // 防⽌外部构造。
Singleton() = default; // 防⽌拷贝和赋值。
Singleton& operator=(const Singleton&) = delete; Singleton(const Singleton& singleton2) = delete;private: static Singleton* singleton_;};Singleton* Singleton::singleton_ = new Singleton;int main() { Singleton* s1 = Singleton::GetInstance(); std::cout << s1 << std::endl; Singleton* s2 = Singleton::GetInstance(); std::cout << s2 << std::endl; Singleton.DestreyInstance(); return0;}2.懒汉模式 饿汉⽅式不论是否需要使⽤该对象都将其定义出来,可能浪费了内存,或者减慢了程序的启动速度。
所以使⽤懒汉模式进⾏优化,懒汉模式即延迟构造对象,在第⼀次使⽤该对象的时候才进⾏new该对象。
单件模式(Singleton)C++实现意图:保证⼀个类仅有⼀个实例,并提供⼀个访问它的全局访问点。
实⽤性:1.当类只能有⼀个实例⽽且客户可以从⼀个众所周知的访问点访问它。
2.当这个唯⼀的实例应该是通过⼦类可扩展的,并且客户应该⽆需更改代码就能使⽤⼀个扩展的实例时。
效果: 1.只有⼀个实例,可以严格的控制客户怎样以及何时访问。
2.缩⼩名空间,避免了唯⼀实例的全局变量污染名空间。
3.可以控制对象的实例个数。
代码⽰例:这⾥类是⼀个⼈Micla,世界上仅有⼀个Mical,只能产⽣⼀个实例。
#ifndef _SINGLETON_#define _SINGLETON_class Mical{public:~Mical(){}static Mical* GetMical(){if(NULL == _mpMical){_mpMical = new Mical;static Delete Del;}return _mpMical;}private:static Mical* _mpMical;////避免了不同情况实例化类对象Mical(const Mical& another){}Mical& operator = (const Mical& another){}Mical(){}};#endif实现部分:#include <iostream>#include "Singleton.h"using namespace std;Mical* Mical::_mpMical = NULL;int main(){Mical* pMical = Mical::GetMical();delete Mical::GetMical();return0;}⽤Mical* pMical = Mical::GetMical(); 实现了访问Micla 然后我们可以通过pMical访问Mical的各种属性(假设为:⾝⾼,性别等)之后通过delete Mical::GetMical(); 删除对象。
C++经典面试题:设计一个类,该类只能实例化一次,用main函数测试这个类单例是因为一个就足够了,多了浪费比如邮局里的电话簿只有一本,有需要的人拿来看,没有必要每个人要查的时候工作人员就拿一本出来,看完了再回收例。
如下面的类定义:#include <iostream>#include <string>using namespace std;class CSingleton{public:static CSingleton *GetInstance();//静态成员函数,返回CSingleton的指针private:CSingleton(){}; //私有的构造函数static CSingleton * m_pInstance; //静态的私有类指针};CSingleton *CSingleton::m_pInstance=NULL;//类的静态成员指针的初始化CSingleton *CSingleton::GetInstance(){if (m_pInstance==NULL)//评定是否为第一个对象.m_pInstance= new CSingleton(); //生成新对象return m_pInstance; //返回CSingleton对象指针}void main(){CSingleton *p=CSingleton::GetInstance();//通过类调用静态成员函数.cout<<p<<endl;cout<<p->GetInstance()<<endl;//根据GetInstance,这里没有new新的出来.}调试输出结果:003807A8003807A8Press any key to continue它有一个指唯一实例的静态指针m_pInstance,并且是私有的。
它有一个公有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。