MessageHandler & Singleton
Para nuestros propósitos necesitamos que exista una única copia de la clase que hace de factoría, además también necesitamos que esta factoría pueda recibir mensajes desde otras partes del juego para crear los elementos según sean necesarios.
Para ello he tomado una clase derivada de MessageHandler y le he dado la forma de singleton.
#ifndef _GEL_GAME_FACTORY_H_ #define _GEL_GAME_FACTORY_H_ #include "Core/MessageHandler.h" #include <map> namespace Gel { namespace Game { class CreatorBase; class BuilderBase; class Factory: public Core::MessageHandler { public: DECLARE_RTTI; /// @fn GetInstance /// @brief Get The Intance of the factory /// /// A singleton static function to create a unique factory static Factory& GetInstance(); /// @fn RegisterCreator /// @brief Add a creator for a messagehandler /// /// Register a creator to make a piece of a game element void RegisterCreator(unsigned int creatorId, const CreatorBase* creator); /// @fn UnregisterCreator /// @brief Eliminate a creator from database void UnregisterCreator(unsigned int creatorId); /// @fn Create /// @brief find and execute the creation of a messagehandler Core::MessageHandler* Create(unsigned int creatorId, const Base::DataPack& extraData); /// @fn RegisterBuilder /// @brief Add a complex game element builder to DB void RegisterBuilder(unsigned int creatorId, const BuilderBase* builder); /// @fn UnregisterBuilder /// @brief Eliminate a Builder from DB void UnregisterBuilder(unsigned int creatorId); /// @fn Build /// @brief Crete a complex game object void Build(unsigned int creatorId, const Base::DataPack& extraData); /// @fn HandleMessage /// @brief Get a message and process it void HandleMessage( unsigned int fromHandlerID, unsigned int messageID, const Base::DataPack& extraData ); /// @fn Notify /// @brief Get a notification and process it void Notify( unsigned int notificationID, const Base::DataPack& extraData ); private: /// @fn (constructor) /// @brief default constructor Factory(); /// @fn (copy constructor) /// @brief copy constructor Factory(const Factory& other); /// @fn operator= /// @brief assignation opetator const Factory& operator=(const Factory& _other); protected: typedef std::map<unsigned int, const CreatorBase*> CreatorMap; typedef std::map<unsigned int, const CreatorBase*>::iterator CreatorIterator; CreatorMap m_creators; typedef std::map<unsigned int, const BuilderBase*> BuilderMap; typedef std::map<unsigned int, const BuilderBase*>::iterator BuilderIterator; BuilderMap m_builders; }; } //End of Game } //End of Gel #endif
Como podéis ver tiene las funciones necesarias de un MessageHandler (HandlerMessage y Notify), y sus constructores son privados, por lo que nadie puede crear una factoría a través de un new, como todo singleton de los que yo utilizo tiene una función static que si es necesario crea la factoría y nos devuelve la instancia única.
Como MessageHandler tiene un ID, sin embargo, este identificador único no nos interesa ya que accedemos a esta clase a través de la función estática.
La Factoría
Un patrón factoría no es mas que un objeto donde se centraliza la creación de los objetos del programa. Para crear un determinado objeto se le indica a la factoría con un identificador que elemento se quiere crear y este te lo devuelve.
Existen muchas formas de hacer una factoría, he optado por un sistema de registros de clases creadoras.
Se tiene una clase creadora, todas derivadas de una clase creadora base, cuyo único objetivo es hacer un new de la clase que se desea crear. Todas esas clases se registran dentro de la factoría con un identificador y de esta forma se pueden crear objetos tan solo diciéndole a la factoría que identificador usar.
Podéis ver en código de arriba como hay dos funciones para registrar y borrar CreatorBase, y una que sirve para crear según un identificador.
El Builder
Un Builder es un patrón de diseño que se utiliza cuando se requiere crear un objeto a partir de varios procesos distintos.
En nuestro caso los elementos de nuestros juegos serán objetos formados por varios MessageHandler ( Datos, Vista Controlador ) de distinto tipo según el objeto que además tienen que crearse en un orden determinado.
Para eso tenemos un objeto cuya única función es crear los distintos elementos en orden y realizar las operaciones necesarias para construir el nuevo elemento.
Podía haber creado otro singleton similar a la factoría de arriba y en el haber registrado y borrado los objetos Builder, sin embargo he preferido meterlo todo en el mismo singleton.
Por ello hay tres funciones, parecidas a las de la factoría, que sirven para mantener un registro de los objetos Builder y poder acceder a ellos. Los objetos Builder a su vez crearan las piezas a través de los Creator.
Conclusión
La creación de objetos esta todavía muy verde y de una forma muy abstracta hasta que no empecemos a usarla en el juego. En realidad es muy sencillo de usar, solo hay que superar el pensamiento de programación lineal.
Gracias por vuestra atención.
1 comentario:
David, ante todo gracias por tus tutos estoy muy agradecido estoy aprendiendo un montón en el área de creación de juegos ahora tengo un proyecto en mente, estoy haciendo la parte del diseño y pensando en las mecánicas antes de meterme de lleno a programar, estoy estudiando ingeniería en sistemas, ademas de que este proyecto me sirve de practica, también me divierte bastante programar, me gustaría que siguieras con tus tutoriales por que en la parte de realizar motores estoy crudo, y repito gracias por estos valiosos tutoriales.
Publicar un comentario