2009-03-31 7 views

Répondre

92

Ce n'est pas une structure de données mais un motif de conception. Vous cherchez le Command Pattern.

La norme consiste à conserver les objets de commande dans une pile pour prendre en charge l'annulation multi-niveau. Afin de prendre en charge refaire, une deuxième pile conserve toutes les commandes que vous avez annulées. Ainsi, lorsque vous faites sauter la pile d'annulation pour annuler une commande, vous appuyez sur la même commande que celle que vous avez introduite dans la pile de rétablissement. Vous faites la même chose à l'envers lorsque vous refaites une commande. Vous faites apparaître la pile de rétablissement et repoussez la commande éclatée dans la pile d'annulation.

+28

Il est également important de toujours effacer la pile Redo si vous appuyez sur une autre commande. – Balk

+10

La structure de données est empilée avec des instances d'objets "Command". – zinovii

+1

J'ai l'impression que le modèle de commande n'est pas nécessairement la façon dont vous mettez en œuvre l'annulation, c'est juste une option, et ce n'est pas non plus la réponse à la question du PO. Les piles d'annulation/rétablissement sont la réponse. (Bien que je suppose qu'il a mentionné MSWord.) –

31

En fait, le modèle standard pour cette fonctionnalité (Gang of Four, même) est Memento.

En outre, alors que la plupart des programmes utilisent Undo/Redo piles, afficionados de certains éditeurs de texte préfèrent Undo/Redo arbres afin qu'ils ne perdent pas leur histoire si elles défont quelques commandes, essayez une nouvelle, et changer d'avis.

+3

Vous avez raison. Si vous ajoutez plus d'informations sur la façon dont il interagit avec le modèle de commande, ce serait une excellente réponse. – Kieveli

+0

Essayez d'effacer l'utilisation de Memento, Est-ce que Memento est utilisé pour stocker l'état des objets avant et après l'opération pour undoo/redo? – NileshChauhan

+1

L'objet qui produit le Memento l'utilise pour revenir à cet état. Le Memento lui-même devrait être traité comme s'il était opaque. Remplir tout l'état dans le Memento semble être un choix d'implémentation évident, mais il pourrait tout aussi bien être un diff, ou un id dans un backing store, ou quelque chose d'autre. –

0

Ceci est un cas classique de motif de commande. Voici un exemple d'implémentation de la fonctionnalité d'annulation en Python:

from os import rename 
class RenameFileCommand(object): 
    def __init__(self, src_file, target_file): 
     self.src_file=src_file 
     self.target_file=target_file 


    def execute(self): 
     rename(self.src_file, self.target_file) 

    def undo(self): 
     rename(self.target_file,self.src_file) 



class History(object): 
    def __init__(self): 
     self.commands=list() 
    def execute(self, command): 
     command.execute() 
     self.commands.append(command) 

    def undo(self): 
     self.commands.pop().undo() 


if __name__=='__main__': 
    hist=History() 
    hist.execute(RenameFileCommand('test1.txt', 'tmp.txt',)) 
    hist.undo() 
    hist.execute(RenameFileCommand('tmp2.txt', 'test2.txt',)) 
Questions connexes