<div dir="ltr">Hola, <br>dejad que introduzca el problema que pretendo resolver para que quede bien explicado. Imaginemos que tenemos un programa que carga imagenes y trabaja con ellas. Las imagenes van a memoria RAM y la carga viene de disco. Nadie quiere cargar la misma imagen dos veces, asi que tenemos que aplicar logica extra para evitarlo. Yo uso una clase que gestiona los recursos. En general, la primera vez que se carga una clase, usando path + nombre (que es unico en cada maquina), la clase se carga en un vector, y la clase CResourceManager devuelve un puntero a la clase. Cuando se intenta crear la clase por segunda vez, CResourceManager, la busca en un mapa, recoge la clave, que es el indice del vector y devuelve el puntero a la informacion. Os pongo un ejemplo de como la implemento:<br>
<br>===================================================================================<br>ResourceManager.h<br>===================================================================================<br>#ifndef _CRESOURCEMANAGER_H_<br>
#define _CRESOURCEMANAGER_H_<br><br><br>#include <vector><br>#include <map><br>#include <iterator><br>#include "SampleResource.h"<br><br>using std::vector;<br>using std::string;<br>using std::map;<br>
using std::iterator;<br><br><br><br>class CResourceManager<br>{<br>    static const unsigned int MAX_ITEMS = 200;<br>    typedef struct stLoadedResource <br>    {<br>        CSampleResource* res;<br>        unsigned int nInstances;<br>
    };<br><br>    map<string,unsigned int>    m_handlesMap;<br>    vector<stLoadedResource>    m_resourceList;<br>    vector<unsigned int>        m_avaiableItems;<br><br>public:<br>    CSampleResource* getResource(string path, string name);<br>
    void releaseResource(string path,string name);<br>    CResourceManager(void);<br>    ~CResourceManager(void);<br>};<br><br>#endif //_CRESOURCEMANAGER_H_<br><br><br>
===================================================================================<br>
ResourceManager.cpp<br>
===================================================================================<br>#include "ResourceManager.h"<br><br>CResourceManager::CResourceManager(void):m_resourceList(MAX_ITEMS)<br>{<br>    for (unsigned int i = 0; i < MAX_ITEMS; i++)<br>
    {<br>        m_avaiableItems.push_back(i);<br>    }<br>}<br><br>CResourceManager::~CResourceManager(void)<br>{<br>}<br><br>CSampleResource* CResourceManager::getResource( string path, string name)<br>{<br>    string fullPath = path + name;<br>
    unsigned int index;<br>    // buscar el elemento en el mapa<br>    map<string,unsigned int>::iterator it = m_handlesMap.find(fullPath);<br>    // si no hemos cargado previamente este recurso<br>    if (it == m_handlesMap.end())<br>
    {<br>        index = m_avaiableItems.back();<br>        // una vez creado lo metemos en el vector en la primera entrada libre que tenemos<br>        m_resourceList[index].nInstances = 0;<br>        m_resourceList[index].res = new CSampleResource();<br>
        m_resourceList[index].res->load(path,name);<br><br>        // y actualizamos el mapa<br>        m_handlesMap[fullPath] = index;<br>        // actualizamos los elementos libres descartando el que hemos usado<br>
        m_avaiableItems.pop_back();<br>    }else<br>    {<br>        index = it->second;<br>    }<br>    m_resourceList[index].nInstances++;    <br>    // y devolvemos el resultado<br>    return m_resourceList[index].res;<br>
}<br><br>void CResourceManager::releaseResource( string path,string name )<br>{<br>    string fullPath = path + name;<br>    unsigned int index;<br>    // buscar el elemento en el mapa<br>    map<string,unsigned int>::iterator it = m_handlesMap.find(fullPath);<br>
    // si hemos cargado previamente este recurso<br>    if (it != m_handlesMap.end()){<br>        index = it->second;<br>        m_resourceList[index].nInstances--;<br>        // si era la ultima instancia<br>        if (m_resourceList[index].nInstances == 0)<br>
        {<br>            delete m_resourceList[index].res;    // llamamos al destructor de la clase<br>            m_resourceList[index].res = NULL;    // ponemos un null de seguridad<br>            m_avaiableItems.push_back(index);    // actualizar la lista de indices vacios<br>
            map.erase(it);                        // borrar la entrada del mapa<br>        }<br>    }<br>    return;<br><br>}<br><br>===================================================================================<br>SampleResource.h<br>


===================================================================================<br>#ifndef _CSAMPLERESOURCE_H_<br>#define _CSAMPLERESOURCE_H_<br><br><br><br>#include <string><br>#include <fstream><br>#include <iostream><br>
#include <vector><br><br>using std::string;<br>using std::cout;<br>using std::fstream;<br>using std::ifstream;<br>using std::vector;<br><br>class CSampleResource//:public IResource<br>{<br>    typedef vector<string> vectorText;<br>
private:<br>    vectorText m_text;<br>public:<br>    /*<br>    void* loadResource(string path, string name, unsigned int hadle){<br>        load(path,name);    <br>        return this;<br>    }<br>    bool releaseResource(){return true;}<br>
    */<br>    void render(){<br>        vector<string>::iterator i = m_text.begin();<br>        while (i != m_text.end())<br>        {<br>            cout << *i++ << std::endl;<br>        }<br>    }<br><br>
    void load(string path, string name){<br>        string fullName = path + name;<br>        ifstream myfile(fullName.c_str());<br>        if (myfile.is_open())<br>        {<br>            while (!myfile.eof())<br>            {<br>
                string s;<br>                getline(myfile,s);<br>                m_text.push_back(s);        <br>            }<br>            myfile.close();<br>        }<br>        else cout << "Unable to open file" << std::endl; <br>
    }<br>    CSampleResource(void){}<br><br>    ~CSampleResource(void){    }<br>};<br><br>#endif //_CSAMPLERESOURCE_H_<br>===================================================================================<br>
Main.cpp<br>


===================================================================================<br><br>#include "SampleResource.h"<br>#include "ResourceManager.h"<br><br>int main () {<br>    CResourceManager resManager = CResourceManager();<br>
    CSampleResource* sr = resManager.getResource("./","log.txt");<br>    CSampleResource* sr2 = resManager.getResource("./","log.txt");<br>    CSampleResource* sr3 = resManager.getResource("./","log2.txt");<br>
    sr->render();<br>    sr2->render();<br>    sr3->render();<br><br>    system("PAUSE");<br>    return EXIT_SUCCESS;<br>}<br>


===================================================================================<br><br>Como podeis ver el diseño tiene algunos errores pero sirve como ejemplo, creo. Ahora viene la pregunta. Mi idea es que si se puede hacer con una clase, por que no hacerlo con varias y gestionar varios tipos de recursos en una sola clase? Al principio habia pensado en hacer un template, y entonces tendria tantos managers como tipos de recursos, pero lo que busco es usar bien el polimorfismo para poder gestionarlas todas en una sola clase. Eso da una serie de problemas de diseño que no consigo responder. Para empezar, la funcion load será diferente para cada clase. Ademas, en getResource se el tipo que tengo que guardar en el vector, pero si tengo varias clases eso ya no vale.<br>
<br>La primera idea que tengo es substituir la funcion de carga por un puntero a funcion, pero, donde lo guardo? Por que esta clase guardará varios tipos de clases, pero de cada clase podra haber varias instancias (una por archivo).<br>
<br>No se.. estoy hecho un lio. Me podeis echar una mano?<br><br clear="all">Ferran<br>
</div>