OGRE分析之设计模式(四)

  • Post author:
  • Post category:其他


OGRE


分析之设计模式(四)







Mythma







Email: mythma@163.com




OGRE


的设计结构十分清晰,这得归功于设计模式的成功运用。




八、




Iterator


说到


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


()只是定义了一个设置顺序。