Мое приложение разработано на C ++ с использованием Qt и использует сигналы и слоты.
Допустим, у меня есть следующие классы (псевдо-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;
};
С моим приложением пользователь может добавлять / удалять игрока, а для каждого игрока решать цвет и размер мяча. За капюшоном GeneralHandler отвечает за хранение шаров и их удаление.
Вполне возможно, что два игрока используют один и тот же мяч.
Когда игрок удаляется, если мяч больше не используется, GeneralHandler должен удалить его (или оставить его, если мяч все еще используется другим игроком).
Если шар, используемый игроком, заменяется, предыдущий шар, если он больше не используется, также должен быть удален GeneralHandler.
Пока все хорошо.
Теперь я хочу добавить возможность отмены / повтора в мое приложение, используя шаблон команды, и это то, где я застрял. Допустим, у меня есть что-то вроде этого:
class ChangePlayerBall : public QUndoCommand
{
public:
ChangePlayerBall(Player* pPlayer, Ball* pNewBall)
{
m_pPlayer = pPlayer;
}
void redo();
void undo();
private:
Player* m_pPlayer;
};
Я думаю, метод redo () будет выглядеть так:
void ChangePlayerBall::redo()
{
m_pPlayer->setBall(pNewBall);
}
Если в приведенном выше коде ничего не изменилось, предыдущий мяч будет удален, если другие игроки больше не будут его использовать.
Это будет проблемой при реализации метода undo (): если предыдущий шар был удален, я не знаю, каковы его характеристики, и команда undo не сможет его воссоздать.
Или, может быть, я должен сохранить предыдущий мяч, но как команда отмены / повторного выполнения узнает, существует ли этот предыдущий мяч или он был удален обработчиком?
Или, может быть, этот механизм удаления шара, как только он больше не используется, должен быть реализован в команде отмены? Проблема в том, что команда отмены будет иметь много зависимостей от многих других классов. Другая проблема заключается в том, что этот код будет частично продублирован в команде DeletePlayer, которая должна будет выполнить нечто подобное:
class DeletePlayer : public QUndoCommand
{
public:
DeletePlayer(Player* pPlayer);
void redo();
void undo();
...
};
Надеюсь, мои объяснения понятны!
Как бы вы решили эту проблему? Я не могу найти удовлетворительное решение.
Спасибо!