desfazer refazer com um mecanismo de auto excluir

votos
0

O meu pedido é desenvolvido em C ++ usando Qt e está a utilizar sinais e ranhuras.

Digamos que eu tenho as seguintes classes (pseudo-código 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;
};

Com o meu aplicativo, o usuário pode adicionar / remover jogador, e para cada jogador, decidir a cor eo tamanho da bola. Atrás do capô, o GeneralHandler é responsável para armazenar as bolas e excluí-los. É perfeitamente possível que dois jogadores estão usando a mesma bola.

Quando um jogador é excluído, se a bola não é mais usado, o GeneralHandler deve excluí-lo (ou mantê-lo se a bola ainda é usado por outro jogador). Se a bola de um jogador está usando é alterado, a bola anterior, se não for mais usado, deve ser excluído pelo GeneralHandler também.

Por enquanto, tudo bem.

Agora, eu quero adicionar a capacidade de desfazer / refazer a minha candidatura, usando o padrão de comando, e isso é onde eu estou preso. Vamos dizer que eu tenho algo parecido com isto:

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

    void redo();
    void undo();

private:
    Player* m_pPlayer;
};

Eu acho que o método redo () será parecido com este:

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

Se nada mais é alterado no código acima, a bola anterior serão excluídos se não mais utilizado por outros jogadores. Isso vai ser um problema quando implementar o método undo (): se a bola anterior ter sido eliminado, eu não sei o que era as suas características e o comando de desfazer não será capaz de recriá-lo. Ou talvez eu deva guardar a bola anterior, mas como vai o comando undo / redo saber se esta bola anterior é ainda existentes ou que foi excluído pelo manipulador? Ou talvez este mecanismo de exclusão de uma bola, logo que ele não é mais usado deve ser implementado no comando de desfazer? O problema é que o comando desfazer vai ter um monte de dependências em muitas outras classes. O outro problema é que este código seria parcialmente duplicada no comando DeletePlayer, que terá que fazer algo semelhante:

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

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

Espero que meus explainations onde compreensível!

Como resolveria este problema ? Não consigo encontrar uma solução satisfatória.

Obrigado !

Publicado 09/12/2008 em 14:50
fonte usuário
Em outras línguas...                            


3 respostas

votos
1

Bola serão excluídos se não mais utilizado por outros jogadores

Como eu posso ver - que s the source of your doubts. Certainly undo() command shouldn't recreate an object nor have ité próprio mecanismo de exclusão. Como a sua GeneralHandler.isNotUsedAnymore () funciona? Se ele conta as referências a bolas, de referência ao exemplo de ChangePlayerBall deve ser também ser contadas. Por isso, será necessário para conectar objeto de comando para alguns slots GeneralHandler`s.

Então, eu gostaria de sugerir:

  1. Bola é excluído quando it`s não está sendo usado por todos os jogadores e nenhum UndoCommands (pode ser inclusive mudança de cor e etc)
  2. Relação entre freios bola eo player na nova atribuição bola como você `ve feito
  3. Relação entre os freios de esferas e de comando no destruidor objecto command`s (quando completamente removido da pilha)

Espero que ajude )

Respondeu 16/12/2008 em 10:08
fonte usuário

votos
0
  1. Salve bola no construtor do comando.
  2. Coloque-in / out quando necessário.
  3. Use QSharedPointer de bola em todos os lugares para evitar vazamentos de memória.
Respondeu 01/12/2010 em 09:12
fonte usuário

votos
0

Que tal usar um truque contagem de referência para a bola? Quando uma bola é armazenado no comando, o comando pode incrementar a contagem de referência para a bola, portanto, impedindo que sejam apagadas pelo manipulador (ou por si só, dependendo de como você mudaria a implementação).

Respondeu 28/05/2009 em 21:26
fonte usuário

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