deshacer la rehacer con un mecanismo de eliminación automática

votos
0

Mi aplicación se desarrolla en C ++ utilizando Qt y está utilizando señales y ranuras.

Digamos que tengo las siguientes clases (código pseudo-C ++):

class Ball
{
    Color m_Color;
    int m_Size;
};

class Player
{
public:
    setBall(Ball* pBall)
    {
        if (pBall != m_pBall)
        {
            Ball* pPreviousBall = m_pBall;
            m_pBall = pBall;
            emit notifyBallNotUsed(pPreviousBall);
        }
    }

    Ball* getBall();

signals:
    void notifyBallNotUsed(Ball*);

private:
    String m_Name;
    Ball* m_pBall;
};

class GeneralHandler
{
public:
    addBall(Ball* pBall);
    deleteBall(Ball* pBall);


    addPlayer(Player* pPlayer)
    {
        connect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));
        ...
    }
    deletePlayer(Player* pPlayer);
    {
        disconnect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));

        onBallUsageChanged(pPlayer->getBall());
        ....
    }

private slots:
    void onBallUsageChanged(Ball* pBall)
    {
        if (isNotUsedAnymore(pBall))
        {
            m_BallList.remove(pBall);
            delete pBall;
        }
    }

private:
    bool isNotUsedAnymore(Ball* pBall); // Check if the given ball is still used by at least one player

    List<Player*> m_PlayerList;
    List<Ball*> m_BallList;
};

Con mi aplicación, el usuario puede agregar / eliminar jugador, y para cada jugador, decidir el color y el tamaño de la pelota. Detrás del capó, el GeneralHandler se encarga de guardar las bolas y eliminarlas. Es perfectamente posible que dos jugadores estén usando la misma pelota.

Cuando se elimina un jugador, si la pelota ya no se usa, GeneralHandler debería eliminarla (o conservarla si todavía la usa otro jugador). Si la pelota que usa un jugador cambia, la bola anterior, si no se usa más, también debe ser eliminada por GeneralHandler.

Hasta aquí todo bien.

Ahora, quiero agregar la capacidad de deshacer / rehacer a mi aplicación, usando el patrón de comando, y aquí es donde estoy atascado. Digamos que tengo algo como esto:

class ChangePlayerBall : public QUndoCommand
{
public:
    ChangePlayerBall(Player* pPlayer, Ball* pNewBall)
    {
        m_pPlayer = pPlayer;
    }

    void redo();
    void undo();

private:
    Player* m_pPlayer;
};

Supongo que el método redo () se verá así:

void ChangePlayerBall::redo()
{
    m_pPlayer->setBall(pNewBall);
}

Si no se cambia nada más en el código anterior, la Bola anterior se eliminará si ya no la utilizan otros jugadores. Esto será un problema al implementar el método undo (): si la bola anterior ha sido eliminada, no sé cuáles fueron sus características y el comando deshacer no podrá recrearla. O tal vez debería guardar la bola anterior, pero ¿cómo sabrá el comando deshacer / rehacer si esta bola anterior aún existe o si el controlador la ha borrado? ¿O tal vez este mecanismo de eliminar una bola tan pronto como ya no se use debería implementarse en el comando de deshacer? El problema es que el comando deshacer tendrá muchas dependencias en muchas otras clases. El otro problema es que este código se duplicará parcialmente en el comando DeletePlayer, que tendrá que hacer algo similar:

class DeletePlayer : public QUndoCommand
{
public:
    DeletePlayer(Player* pPlayer);

    void redo();
    void undo();
...
};

¡Espero que mis explicaciones sean comprensibles!

Como resolverías este problema ? No puedo encontrar una solución satisfactoria.

Gracias !

Publicado el 09/12/2008 a las 14:50
fuente por usuario
En otros idiomas...                            


3 respuestas

votos
1

La bola será eliminada si ya no la usan otros jugadores

Como puedo ver, s the source of your doubts. Certainly undo() command shouldn't recreate an object nor have ites un mecanismo de eliminación propio. ¿Cómo funciona su GeneralHandler.isNotUsedAnymore ()? Si cuenta las referencias a las bolas, también se debe contar la referencia a la instancia de ChangePlayerBall. Por lo tanto, será necesario conectar el objeto Command a algunos slots de GeneralHandler.

Entonces, sugeriría:

  1. La bola se elimina cuando no está siendo utilizada por ningún jugador ni por ningún UndoCommands (puede incluir cambios de color, etc.)
  2. Vinculación entre bola y jugador frena en la nueva asignación de bola como lo has hecho
  3. Enlace entre la bola y los frenos de comando en el destructor de objetos del comando (cuando se eliminó por completo de la pila)

Espero eso ayude )

Respondida el 16/12/2008 a las 10:08
fuente por usuario

votos
0
  1. Salvar bola en el constructor del comando.
  2. Ponerlo de entrada / salida cuando sea necesario.
  3. Utilice QSharedPointer para la bola por todos lados para evitar pérdidas de memoria.
Respondida el 01/12/2010 a las 09:12
fuente por usuario

votos
0

¿Qué le parece usar un truco de conteo de referencia para la pelota? Cuando se almacena una bola en el comando, el comando puede incrementar el recuento de referencia de la bola, lo que evita que el controlador lo elimine (o por sí solo, dependiendo de cómo cambiaría la implementación).

Respondida el 28/05/2009 a las 21:26
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more