您的位置:首页 > 其它

OGRE分析之设计模式 iterator

2010-05-20 23:49 357 查看
一、Singleton

Singleton 模式是OGRE中用的最广泛的设计模式,若干类都使用了该模式。Singleton模式本身很简单,实现方式多种多样,简单的如GoF提到的实现方式,复杂的有Loki库中解决方案,而OGRE的实现方法也是十分简单。
OGRE提供了一个模板类——Ogre::Singleton<T>,作为所有singleton类的基类: 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; } };
需要使用Singleton的类,只需要从它继承即可: class MyClass : public Singleton<MyClass>{//..}
但在OGRE的源码中我们可以发现,从Singleton继承的类都Override了Singleton的成员getSingleton和getSingletonPtr。OGRE中是这样解释的:
Singleton的实现都在OgreSingleton.h文件中,这意味着任何包含OgreSingleton.h头文件的文件编译后都有Singleton的一份实现,这符合模板机制。但是从别的dll中使用基于Singleton的类时,就会产生连接错误。子类Override一下,把实现放在.cpp中,就会避免该问题。

二、 Factory Method
Factory Method本质上代理某个类的实例化过程,封装了一个new的语句而已。C++中new和delete通常都要成对出现,因此Factory Method也应该负责一个对象的delete(GoF没有提到由Factory Method构造的对象的析构问题)。另外,当一个类的构造函数的参数很多,其中有可以提供默认值的时候,用Factory Method还可以简化对象的创建。
OGRE中用到的Factory Method的地方很多。为满足最普遍的情况,OGRE有一个模板化的Factory Method——Ogre::FactoryObj< T >。因为具体类的构造函数的参数并不都相同,因此Ogre::FactoryObj< T >并不是OGRE所有工厂方法的基类。 template< typename T > class FactoryObj { public: virtual ~FactoryObj() {}; virtual const String& getType() const = 0; virtual T* createInstance( const String& name ) = 0; virtual void destroyInstance( T* ) = 0; };
OGRE大部分Factory Method的使用效果都是连接平行的类层次,如:
不使用Ogre::FactoryObj< T >的Factory Method很多,如:
还有ParticleEmitter和 ParticleEmitterFactory两个比较大的类层次等。

三、 Abstract Factory
Abstract Factory提供了用来创建一系列相关或相互依赖对象的接口。对使用者而言,无需关心使用的是何种具体的对象。OGRE中,该模式体现在它的Plug-in机制。
OGRE提供了Plug-in机制。利用Plug-in,一方面把与平台相关的部分和与平台无关的部分分离开来,如底层渲染系统既可以使用OpenGL,又可以使用DirectX;另一方面便于系统功能的扩充,如场景既可以使用BSP方式管理,又可以用Octree管理。
OGRE的Plug-in实现方式有两种,自此只讨论一下用Abstract Factory模式实现的Plug-in。以此方式实现的主要有两大类Plug-in:RenderSystem_x和Plugin_xSceneManager。
1、RenderSystem
RenderSystem是与渲染引擎相关的部分,如RenderSystem_Direct3D7.dll、RenderSystem_Direct3D9.dll、RenderSystem_GL.dll:
与渲染相关的对象都是通过具体的子RenderSystem创建的,这样就形成了不同类别的Render产品。在使用OGRE的时候,只需关心RenderSystem,而无需关心究竟是那种具体的RenderSystem。
RenderSystem创建的产品主要有:
1)RenderWindow
2) RenderTexture
3) HardwareOcclusionQuery

2、SceneManager
SceneManager是与场景内数据的组织方式相关的部分,如:Plugin_OctreeSceneManager.dll、Plugin_BSPSceneManager.dll等:
同样,SceneManager只是个接口,具体的场景管理是由子类完成的。它的产品系主要有:
1)SceneNode
2)RaySceneQuery
SceneManager中的很多Products是相同的,因此由SceneManager就完成创建过程。所以说SceneManager不是个纯粹的Abstract Factory。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pizi0475/archive/2010/03/17/5387619.aspx

MapIterator
说到Iterator,让人首先想到的是STL中各种iterators。OGRE源码中广泛用到了STL,尤其是容器map。但OGRE大部分情况下并没有直接使用与容器配套的迭代器,而是在iterator上包了一层。对序列式容器的iterator,OGRE包装为VectorIterator<T>,其const形式为ConstVectorIterator;对关联式容器(map),包装为MapIterator<T>,其const形式为ConstMapIterator。所以从另一个角度看,使用的是Adapter模式。

OGRE的包装本身没有什么复杂,看一下map的iterator封装就清楚了:

template <class T>
class MapIterator
{
private:
typename T::iterator mCurrent;
typename T::iterator mEnd;
/**//// Private constructor since only the parameterised constructor should be used
MapIterator() {};
public:
typedef typename T::mapped_type MappedType;
typedef typename T::key_type KeyType;
/**//** Constructor.
@remarks
Provide a start and end iterator to initialise.
*/
MapIterator(typename T::iterator start, typename T::iterator end)
: mCurrent(start), mEnd(end)
{
}
/**//** Returns true if there are more items in the collection. */
bool hasMoreElements(void) const
{
return mCurrent != mEnd;
}
/**//** Returns the next value element in the collection, and advances to the next. */
typename T::mapped_type getNext(void)
{
return (mCurrent++)->second;
}
/**//** Returns the next value element in the collection, without advancing to the next. */
typename T::mapped_type peekNextValue(void)
{
return mCurrent->second;
}
/**//** Returns the next key element in the collection, without advancing to the next. */
typename T::key_type peekNextKey(void)
{
return mCurrent->first;
}
/**//** Required to overcome intermittent bug */
MapIterator<T> & operator=( MapIterator<T> &rhs )
{
mCurrent = rhs.mCurrent;
mEnd = rhs.mEnd;
return *this;
}
/**//** Returns a pointer to the next value element in the collection, without
advancing to the next afterwards. */
typename T::pointer peekNextValuePtr(void)
{
return &(mCurrent->second);
}
/**//** Moves the iterator on one element. */
void moveNext(void)
{
mCurrent++;
}

};

九、Observer

Observer模式“定义对象间一对多的依赖关系,当一个对象的状态发生变化时,所有依赖他的对象都得到通知并自动更新”。回想一下OGRE的消息机制,用的正是该模式。

为了得到OGRE的各种消息(更新、鼠标、键盘),在初始化EventProcessor后需要向它添加各种Listeners:KeyListener、MouseListener、MouseMotionListener。而EventProcessor本身又是个FrameListener,在它startProcessingEvents的时候,又以FrameListener的身份注册到Root中。可以看出,Root是消息的发布者,EventProcessor 是个代理,它把消息分发给各种订阅者KeyListener、MouseListener或MouseMotionListener。

至于消息是如何分发的,可以参考Chain of Responsibility模式或消息机制分析。

十、Strategy

Strategy模式在于实现算法与使用它的客户之间的分离,使得算法可以独立的变化。

回想一下Bridge模式,可以发现,两者之间有些相似性:使得某一部分可以独立的变化。只不过Bridge是将抽象部分与它的实现部分分离。从两者所属的类别来看,Bridge强调静态结构,而Strategy强调更多的是行为——算法的独立性。

同样是Bridge模式中的例子,若把Mesh各版本文件读取的实现看作是算法,把MeshSerializer看作是算法的客户,那么该例也可以看作是Strategy模式。具体参考Bridge模式。

从上面可以看出,模式之间本没有绝对的界限,从不同的角度看可以得到不同的结论;另一方面,模式的实现也是随机应变,要与具体的问题想结合。

十一、Template Method

Template Method比较简单的一个模式,属于类行为模式。可以用“全局与细节”、“步骤与实现”来概括,具体就是基类定义全局和步骤,子类来实现每一步的细节。

OGRE给的Example框架使用了该模式,并具代表性。看一下ExampleApplication的setup()成员:

bool setup(void)
{
mRoot = new Root();

setupResources();

bool carryOn = configure();
if (!carryOn) return false;

chooseSceneManager();
createCamera();
createViewports();

// Set default mipmap level (NB some APIs ignore this)
TextureManager::getSingleton().setDefaultNumMipmaps(5);

// Create any resource listeners (for loading screens)
createResourceListener();
// Load resources
loadResources();

// Create the scene
createScene();

createFrameListener();

return true;

}

该成员函数调用的其他virtual成员函数都有默认的实现,若不满足需求,子类可以自行实现。而setup()只是定义了一个设置顺序。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pizi0475/archive/2010/03/17/5387592.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: