两种用于派生的Singleton模式(以TextureMgr为例)

来源:互联网 发布:唯歌生民病 愿得天子知 编辑:程序博客网 时间:2024/06/05 18:19

  Singleton,顾名思义,从字面上来理解就是单例模式,这是C++程序中

常用到的一种设计模式,特别是像文件管理器,纹理管理器这种整个软件

中只需要唯一的实例来管理所有资源时,这种模式的价值便得以体现。

  下面来介绍两种用于派生管理的Singleton模式:

  其中,第一种是Gof版本的Singleton, 其代码如下:

//【Singleton_Gof.h】#pragma  oncetemplate<typename T>class Singleton_Gof{protected:static T* ms_Singleton;Singleton_Gof(){assert(!ms_Singleton);}~Singleton_Gof(){assert(ms_Singleton);ms_Singleton=NULL;}private:Singleton_Gof(const Singleton_Gof&); //防止构造函数的复制Singleton_Gof& operator=(const Singleton_Gof&);public:static T* getSingletonPtr(){if (!ms_Singleton)ms_Singleton = new T();return ms_Singleton;}static T& getSingleton(){if (!ms_Singleton)ms_Singleton = new T();return (*ms_Singleton);}}; template<typename T>T* Singleton_Gof<T>::ms_Singleton = NULL;

  其大致上的原理便是在需要初始化时,将静态的Singleton实例指向派生类T对象,

  类似的,还有第二种Singleton, 其代码如下:

//【Singleton.h】#pragma once#include <cassert>template<typename T>class Singleton{private:Singleton(const Singleton<T>&);Singleton& operator=(const Singleton<T> &);protected:static T* ms_Singleton;Singleton(){assert(!ms_Singleton);#if defined( _MSC_VER ) && _MSC_VER < 1200  int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;ms_Singleton = (T*)((int)this + offset);#elsems_Singleton = static_cast< T* >( this );#endif};~Singleton(){assert(ms_Singleton); ms_Singleton = NULL;}public:static T& getSingleton(){if(!ms_Singleton)new T(); return (*ms_Singleton);}static T* getSingletonPtr(){if(!ms_Singleton)new T(); return ms_Singleton;}};template<typename T>T* Singleton<T>::ms_Singleton = NULL;

        Singleton()里的代码在OGRE和《游戏编程精粹》都出现过,这里涉及VC编译器的内存对齐,就不详细讲解了,

        然后我们便可以利用上面的Singleton()代码派生出一个纹理管理器来,我这里粗略写了下:

//【TextureMgr.h】#include <string>#include <map>#include <iostream>#include "Singleton.h"#include "Singleton_Gof.h"using namespace std;//Textureclass Texture{private:string m_Name;public:Texture(const string name):m_Name(name){load();};~Texture(){unload();}const string& getName()const {return m_Name;}bool load(){cout<<"加载了一张纹理:"+m_Name<<endl;return true;}bool unload(){cout<<"从资源中清除一张纹理:"+m_Name<<endl;return true;}void doSomeThing(){cout<<"对纹理:"+m_Name+",进行了某些操作"<<endl;}};typedef std::map<string, Texture*> texMap;typedef texMap::iterator texMapIter;#define SAFE_DELETE(p) {if(p){delete p;p=NULL;}}//TextureMgrBaseclass TextureMgrBase{texMap m_TiMap;public:Texture* getTexture(const string name){texMapIter iter = m_TiMap.find(name);if(iter == m_TiMap.end()){Texture* tex = new Texture(name);m_TiMap.insert(std::make_pair(name, tex));return tex;}else{return iter->second;}}TextureMgrBase(){cout<<"TextureMgrBase constructor"<<endl;}~TextureMgrBase(){for(texMapIter iter = m_TiMap.begin();iter!=m_TiMap.end();iter++){SAFE_DELETE(iter->second);}cout<<"TextureMgrBase destructor"<<endl;}};//TextureMgrclass TextureMgr:public TextureMgrBase, public Singleton<TextureMgr>{public:TextureMgr(){cout<<"TextureMgr constructor"<<endl;}~TextureMgr(){cout<<"TextureMgr destructor"<<endl;}};//TextureMgrGofclass TextureMgr_Gof:public TextureMgrBase, public Singleton_Gof<TextureMgr_Gof>{public:TextureMgr_Gof(){cout<<"TextureMgr_Gof constructor"<<endl;}~TextureMgr_Gof(){cout<<"TextureMgr_Gof destructor"<<endl;}};

因为加了断言保证只有一次调用,所以就能全局唯一了,因此我们便可以如下来使用这纹理管理器(需要手动删除):

//【main.cpp】#include "TextureMgr.h"#include<iostream>using namespace std;#define  g_TexMgr TextureMgr::getSingleton()#define  g_TexMgr_Gof TextureMgr_Gof::getSingleton()int main(char argc, char* argv[]){//TextureMgrTexture* tex1 = g_TexMgr.getTexture("纹理1");Texture* tex2 = g_TexMgr.getTexture("纹理2");Texture* _tex1 = g_TexMgr.getTexture("纹理1");cout<<tex1->getName()<<endl;cout<<tex2->getName()<<endl;cout<<_tex1->getName()<<endl;tex1->doSomeThing();tex2->doSomeThing();_tex1->doSomeThing();delete &g_TexMgr;cout<<endl;//TextureMgr_GofTexture* tex3 = g_TexMgr_Gof.getTexture("纹理3");Texture* tex4 = g_TexMgr_Gof.getTexture("纹理4");Texture* _tex3 = g_TexMgr_Gof.getTexture("纹理3");cout<<tex3->getName()<<endl;cout<<tex4->getName()<<endl;cout<<_tex3->getName()<<endl;tex1->doSomeThing();tex2->doSomeThing();_tex3->doSomeThing();delete &g_TexMgr_Gof;system("pause");return 0;}

得到的最终结果如下:


1 0
原创粉丝点击