当前位置: 代码迷 >> 综合 >> Ogre不负责任研究(二)单件模式的运用,Ogre::Singleton
  详细解决方案

Ogre不负责任研究(二)单件模式的运用,Ogre::Singleton

热度:4   发布时间:2023-12-10 13:53:55.0

本篇着重分析一下,在Ogre引擎中单件模式是如何被运用的,也就是Ogre::Singleton类的分析和使用。在开始之前,再次感叹一下,高手写的东西就是不一样,不仅仅照顾了不同的编译器,(GCC),还照顾了VC编译器的不同版本其中有一个地方这样写道:

#if defined( _MSC_VER ) && _MSC_VER < 1200  
     int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
     ms_Singleton = (T*)((int)this + offset);
#else
     ms_Singleton = static_cast< T* >( this );

娘的,第二行和第三行是什么意思?分析了半天,我猜,应该是和下面那一句的等价的。是为了那些早期的VC编译器,不支持static_cast方法的编译器,提供一个静态转换的方法,今天也算是学到东西了- -,居然可以这样做静态转换。去掉一些乱起八糟的我看不懂但是还可能有用的东西,剩下的“干货”是酱紫的。

#pragma once

#include "OgrePrerequisites.h"

namespace Ogre {

    /** Template class for creating single-instance global classes. */

   template <typename T> class Singleton

    {

    protected:

        static T* ms_Singleton;

    public:

        Singleton( void ){

        assert( !ms_Singleton );

        ms_Singleton = static_cast< T* >( this );

        }

        ~Singleton( void )

            { assert( ms_Singleton ); ms_Singleton = 0; }

        static T& getSingleton( void )

         {    assert( ms_Singleton ); return ( *ms_Singleton ); }

        static T* getSingletonPtr( void )

         { return ms_Singleton; }

    };

}

 

是滴,Ogre声明了一个基类,Singleton,它同时是一个模板类,所有需要单件模式的实体类,可以继承这个基类,通过继承的方式得到单件模式。例如,号称是“万物之源”的Root类都继承了Singleton类。这个对咱来说还是有点新,可能是咱太弱弱了吧。写了一个Demo来作为Ogre单件模式的分析演示程序。简要代码如下:

//-----Singleton.h-----------基类--模板类-----------------

#pragma once
#include <iostream>
using namespace std;

//模板基类的单件模式演示:

namespace hawkwang{

template<typename T>
class Singleton
{
protected:
   static T* ms_Singleton;
public:
   Singleton(void){
    assert(!ms_Singleton);
    ms_Singleton = static_cast< T* >(this);
    cout<<"Singleton constructor!"<<endl;
   }
   ~Singleton(void){
    assert(ms_Singleton);
    ms_Singleton = 0;
   }
   static T* getSingletonPtr(void){
    return ms_Singleton;
   }
   static T& getSingleton(void){
    assert(ms_Singleton);
    return (*ms_Singleton);
   }
};
}

这里需要注意一下,ms_Singleton 一定是一个静态成员变量,同理,getSingleton和getSingletonPtr方法也是一样,静态的类。

//---------BananaTree.h---香蕉树类头文件,实体类------

#pragma once
#include "Singleton.h"

namespace hawkwang{
class BananaTree:public Singleton<BananaTree>
{
public:
   BananaTree();
   ~BananaTree();
   void Banana();
   static BananaTree* getSingletonPtr(void);
   static BananaTree& getSingleton(void);
};
}

//-----BananaTree.cpp---橡胶类的源文件----------------------

#pragma once
#include "stdafx.h"
#include "BananaTree.h"
#include <iostream>
using namespace std;

namespace hawkwang{
template<> BananaTree* Singleton<BananaTree>::ms_Singleton = 0;
BananaTree& BananaTree::getSingleton(){
   assert(ms_Singleton);
   return (*ms_Singleton);
}

BananaTree* BananaTree::getSingletonPtr(){
   return ms_Singleton;
}

BananaTree::BananaTree(){cout<<"Constructor of BananaTree"<<endl;}
BananaTree::~BananaTree(){cout<<"Destructor of BananaTree"<<endl;}
void BananaTree::Banana(){cout<<"I am a lovely Banana"<<endl;}
}

//-------------AppleTree.h----苹果树类的头文件,实体类------

#pragma once
#include "Singleton.h"

namespace hawkwang{
class AppleTree:public Singleton<AppleTree>{
public:
   AppleTree();
   ~AppleTree();
   void Apple();
   static AppleTree& getSingleton(void);
   static AppleTree* getSingletonPtr(void);
};
}

//------AppleTree.cpp----苹果树类源代码--------

#pragma once

#include "stdafx.h"
#include "AppleTree.h"
#include <iostream>
using namespace std;

namespace hawkwang{
template<> AppleTree* Singleton<AppleTree>::ms_Singleton = 0;

AppleTree* AppleTree::getSingletonPtr(){return ms_Singleton;}
AppleTree& AppleTree::getSingleton(){assert(ms_Singleton); return (*ms_Singleton);}
AppleTree::AppleTree(){cout<<"Constructor of AppleTree"<<endl;}
AppleTree::~AppleTree(){cout<<"Destructor of AppleTree"<<endl;}
void AppleTree::Apple(){cout<<"I am a lovely Apple"<<endl;}
}

//--------main函数---------------------------------

#include "stdafx.h"
#include "BananaTree.h"
#include "AppleTree.h"
#include <iostream>

using namespace hawkwang;

int _tmain(int argc, _TCHAR* argv[])
{
BananaTree bananaRoot;
AppleTree appleRoot;

BananaTree::getSingleton().Banana();
AppleTree::getSingleton().Apple();

char c;
std::cin>>c;

return 0;
}

喔喔,果然高手写的东西就是不一样啊。通过一个模板类,使Singleton类作为其他类的基类,所有需要单件模式的实体类,只需要继承SIngleton类,并实现getSingleton,和getSingletonPtr方法即可。注意,初始化基类ms_Singleton静态成员变量的方法:

template<> AppleTree* Singleton<AppleTree>::ms_Singleton = 0;

注意,静态成员函数在AppleTree类还要再声明一边!因为是静态的拉……。那么,单件是怎么样体现出来的呢?看SIngleton类的代码:

    assert(!ms_Singleton);

这个断言,如果Singleton已经被赋值了,再次调用构造函数的时候,这个断言为假,这时候,就会报错了。这个看似粗暴的方式,实现了通过模板基类和派生的方式的单件模式。灵活性的代价,就是粗暴……,但是确实可以有效的保证继承了SIngleton类的派生类只有一个实例。

访问单件的方法,很简单“类名::getSingleton”“类名::getSingletonPtr”注意SIngleton类只是为了实现单件,而不是为了多态性,所以,不要试图用Singleton类当接口,以多态的方式操作他的派生类。

  相关解决方案