I need to implement Undo/Redo frame work for my window application(editor like powerpoint), what should be the best practice to follow, how would be handle all property changes of my objects and it reflection on UI.
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
The classic practice is to follow the Command Pattern.
You can encapsulate any object that performs an action with a command, and have it perform the reverse action with an Undo() method. You store all the actions in a stack for an easy way of rewinding through them.
There are two classic patterns to use. The first is the memento pattern which is used to store snapshots of your complete object state. This is perhaps more system intensive than the command pattern, but it allows rollback very simply to an older snapshot. You could store the snapshots on disk a la PaintShop/PhotoShop or keep them in memory for smaller objects that don't require persistence. What you're doing is exactly what this pattern was designed for, so it should fit the bill slightly better than the Command Pattern suggested by others.
Also, an additional note is that because it doesn't require you to have reciprocal commands to undo something that was previously done, it means that any potentially one way functions [such as hashing or encryption] which can't be undone trivially using reciprocal commands can still be undone very simply by just rolling back to an older snapshot.
Also as pointed out, the command pattern which is potentially less resource intensive, so I will concede that in specific cases where:
the command pattern may be a better fit [but not necessarily, it will depend very much on the situation]. In other cases, I would use the memento pattern.
I would probably refrain from using a mashup of the two because I tend to care about the developer that's going to come in behind me and maintain my code as well as it being my ethical responsibility to my employer to make that process as simple and inexpensive as possible. I see a mashup of the two patterns easily becoming an unmaintainable rat hole of discomfort that would be expensive to maintain.
There are three approaches here that are viable. Memento Pattern (Snapshots), Command Pattern and State Diffing. They all have advantages and disadvantages.
I would go with State Diffing if you can get away with it as it combines memory reduction with ease of implementation and maintainability.
Note that the VoxelShop mentioned in the article is open source. So you can take a look at the complexity of the command pattern here: https://github.com/simlu/voxelshop/tree/develop/src/main/java/com/vitco/app/core/data/history
Below is excerpt from the article:
Memento Pattern
Pros
Cons
Command Pattern
Pros
Cons
State Diffing
Pros
Cons / Limitations
Reference:
https://www.linkedin.com/pulse/solving-history-hard-problem-lukas-siemon
Take a look at the Command Pattern. You have to encapsulate every change to your model into separate command objects.
I wrote a really flexible system to keep track of changes. I have a drawing program which implements 2 types of changes:
Base class:
Derived class for adding shapes:
Derived class for removing shapes:
Derived class for property changes:
With each time Vormen = the array of items that are submitted to the change. And it should be used like this:
Declaration of the stacks:
Adding a new shape (eg. Point)
Removing a selected shape
Registering a property change
Finally the Undo/Redo action
I think this is the most effective way of implementing a undo-redo algorithm. For an example, look at this page on my website: DrawIt.
I implemented the undo redo stuff at around line 479 of the file Tekening.cs. You can download the source code. It can be implemented by any kind of application.