Undo/Redoを実装(C#)
C#で汎用的に使える(と思われる)Undo/Redoを実装したので紹介します.
アルゴリズムも後ろの方で紹介します.
環境
C# 6.0~が必要です.
ソース (GitHub)
こちら
理論はいいからともかく利用したいという方は上記リンクからダウンロードして, History.csを自分のプロジェクトに追加してください.
使い方
GitHubで公開しているサンプルコードを参考にして下さい.
(ぼくのかんがえたさいきょうの)アルゴリズム
内部でどんなことしてるのか知りたい人向けです.
ここのリビジョン:bd758f6e01c73fd7ea3ba6444d7441a59691275a
のソースコードをもとに説明します.
Commandパターンの利用
デザインパターンの一つであるCommandパターンを利用します.
メソッドの実行時にこれをインスタンスとして保存しておくことで,
「取り消す操作を実行する」「再び実行する」事が可能になります.
概念図
State(状態)とCommand(Undo/Redo操作)によるリンクリストになっています.
初期段階では, 一つのStateだけが存在しています.
Record
実際に処理を実行し, Undo/Redo可能な操作として記録します.
- 処理を実行し, Commandを作成する
- 新しいStateを作成し, 図のようなリンクリストを構築する
- 追加されたStateに遷移する
Undo
Commandに記録しておいた「打ち消す処理」を実行します
- 図のように「前のStateから遷移する時に実行されたCommand」のUndoを実行する
- 前のStateに遷移する
Redo
次のStateへ遷移し, 登録しておいたCommandの処理を実行します
- 「次のStateへ遷移する時に実行されるCommand」のDoを実行する
- 次のStateへ遷移する
Record前にUndoしていたら
下の図のように, Undoしてから新たな処理を実行する場合は, 「次に遷移するStateがある状態」で新たなStateの作成をしなければなりません.
その場合, 現在より後ろのStateは全て破棄します.
Transaction
複数の操作を一つの操作としてまとめることもできます.
Commandの配列をもつCommandクラスを用意してあげれば良いですね.
詳細はTransactionCommandクラスを見てください.
余談
そもそもStateの存在可否から考えた方が良いかも知れない...
Commandの格納にQueueを使って, よりメモリ効率・実行速度の良い実装ができそうな気がしています.
お付き合い頂きありがとうございました.