我的应用程序是使用Qt在C ++中开发的,并且正在使用信号和插槽。
假设我有以下类(伪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);
}
如果上面的代码中没有其他任何内容发生变化,如果其他玩家不再使用,前一个Ball将被删除。 这在实现undo()方法时会出现问题:如果前一个球被删除,我不知道它的特征是什么,撤消命令将无法重新创建它。 或者也许我应该存储前一个球,但是如果前一个球仍然存在或已被处理程序删除,undo / redo命令将如何知道? 或者也许这种在不再使用时删除球的机制应该在撤销命令中实现?问题是undo命令会对很多其他类有很多依赖。另一个问题是这个代码会在DeletePlayer命令中部分重复,它必须做类似的事情:
class DeletePlayer : public QUndoCommand
{
public:
DeletePlayer(Player* pPlayer);
void redo();
void undo();
...
};
我希望我的解释可以理解!
你会如何解决这个问题?我找不到令人满意的解决方案。
谢谢!
答案 0 :(得分:1)
如果不使用,球将被删除 其他球员再也没有了
我可以看到 - 它s the source of your doubts. Certainly undo() command shouldn't recreate an object nor have it
拥有自己的删除机制。您的GeneralHandler.isNotUsedAnymore()如何工作?如果计算对球的引用,则还应计算对ChangePlayerBall实例的引用。因此,需要将Command对象连接到一些GeneralHandler的插槽。
所以,我建议:
希望有所帮助)
答案 1 :(得分:0)
如何使用球的引用计数技巧?当球存储在命令中时,该命令可以增加球的引用计数,从而防止被处理程序删除(或者自身,取决于您将如何更改实现)。
答案 2 :(得分:0)