Do/Undo using command pattern in Python

后端 未结 2 556
北荒
北荒 2021-01-16 15:05

I have read that using command pattern is one of the most popular ways to accomplish do/undo functionality. In fact, I have seen that it\'s possible to stack a bunch of acti

2条回答
  •  臣服心动
    2021-01-16 15:57

    How I'd go about this

    class Command(object):
        def execute(self, canvas):
             raise NotImplementedError
    
    class DrawLineCommand(Command):
        def __init__(self, point1, point2):
            self._point1 = point1
            self._point2 = point2
    
        def execute(self, canvas):
            canvas.draw_line(self._point1, self._point2)
    
     class DrawCircleCommand(Command):
         def __init__(self, point, radius):
            self._point = point
            self._radius = radius
    
         def execute(self, canvas):
            canvas.draw_circle(self._point, self._radius)
    
    class UndoHistory(object):
        def __init__(self, canvas):
            self._commands = []
            self.canvas = canvas
    
        def command(self, command):
            self._commands.append(command)
            command.execute(self.canvas)
    
        def undo(self):
            self._commands.pop() # throw away last command
            self.canvas.clear()
            for command self._commands:
                command.execute(self.canvas)
    

    Some thoughts:

    1. Trying to undo an action can be hard. For example, how would you undraw a line? You'd need to recover what used to be under that line. A simpler approach is often to revert to a clean slate and then reapply all the commands.
    2. Each command should be contained in a single object. It should store all of the data neccesary for the command.
    3. In python you don't need to define the Command class. I do it to provide documentation for what methods I expect Command objects to implement.
    4. You may eventually get speed issues reapplying all the command for an undo. Optimization is left as an excersize for the reader.

提交回复
热议问题