【IT168 專稿】
簡介
我們如何在不同的場景下使用這些方法來實現Undo/Redo。這些方法是使用單個對象表示變化,命令模式和備忘錄模式。
正如我們所知,Undo/Redo沒有通用的解決方案,而Undo/Redo在每個應用程式中非常具體。處於這個原因,在該系列文章的開始部分,將討論如何使用該方法建模任意的應用程式,然後展示一個簡單應用程式的實現。
關於Undo/Redo實現的基本思想
正如我們所知,應用程式在每次操作後改變其狀態。當操作應用程式時,它的狀態會發生改變。所以,若有人想要做撤銷,他不得不回到先前的狀態。因此,為了能夠回到先前狀態,我們需要在應用程式運行時存儲它的狀態。要支持重做,我們不得不從目前狀態跳到下一個狀態。
為了實現Undo/Redo,我們不得不存儲應用程式的狀態並在撤銷時跳到前一個狀態而在重做時跳到下一個狀態。因此我們需要維護應用程式的狀態來支持Undo/Redo。在所有三種方法中,應用程式狀態的維護用到了兩個棧。一個棧包含用於撤銷操作的狀態,第二個包含用於重做的狀態。撤銷操作彈出撤銷棧以獲取前一個狀態並將其設置給應用程式。同樣的,重做操作彈出重做棧以獲取下一個狀態並將其設置給應用程式。
現在,我們知道了Undo/Redo的實現操作都是關於保持應用程式每次操作後的狀態。現在的問題是該方法如何保存狀態。本方法中,單個操作的改變被保存在一個對象中,有些屬性為該操作作為狀態是多餘的,因為這裡,單個對象被用於包含所有類型的動作數據。
什麼是單個對象表示改變的方法?
首先,我對這是由我命名表示抱歉。這裡,單個對象表示了應用程式中所有操作的所有改變。因此,當你準備了一個關於操作更改的類型的對象,在執行一次操作後,你僅使用了該對象屬性的子集,而剩餘屬性仍舊沒有被使用。例如,你在一個應用程式中有兩個操作;它們是高度的改變和寬度的改變。因此,對象類型包含兩個屬性:高度和寬度。當你準備了變化對象,在執行高度更改方法後,你僅需設置變化對象的高度欄位,而其他欄位仍舊沒有被使用。
如何應用單個對象表示變化的方法對任意應用程式Undo/Redo操作建模?
單個對象表示變化的方法如何對任意應用程式Undo/Redo操作建模將在以下步驟中討論:
步驟1
首先識別出你希望哪些操作能支持Undo/Redo。然後,識別出你將在哪個容器下支持Undo/Redo以及你希望哪些對象支持Undo/Redo。
步驟2
為了進一步處理每個Undo/Redo操作,識別出需要被保存的屬性。
步驟3
然後創建一個類(ChangeRepresentationObject),它包含支持全部操作Undo/Redo的所有屬性。同樣,準備一個動作類型enum,它將代表全部操作。這個動作類型enum是ChangeRepresentationObject類的一部分。
步驟4
然後創建一個名為UndoRedo的類,它包含兩個類型的ChangeRepresentationObject棧。一個用於撤銷操作,一個用於重做操作。該類將實現以下接口:
interface IUndoRedo
{
void Undo(int level);
void Redo(int level);
void InsertObjectforUndoRedo(ChangeRepresentationObject dataobject);
}
步驟5
然後實現具體方法:Undo、 Redo、InsertObjectforUndoRedo。
在每個Undo操作中:
•首先檢查Undo棧是否為空。
•如果不是,則彈出一個ChangeRepresentationObject並將其壓入重做棧。
•檢查動作類型。
•然後基於動作類型,利用ChangeRepresentationObject的屬性完成撤銷操作。
在每個Redo操作中,你幾乎做與Undo同樣的事。
•首先檢查Redo棧是否為空。
•如果不是,彈出一個ChangeRepresentationObject,然後將其壓入撤銷棧。
•檢查動作類型。
•然後基於動作的類型,利用ChangeRepresentationObject屬性完成重做操作。
在InsertObjectforUndoRedo操作中,你只要把數據對象插入Undo棧並清空Redo棧中。
步驟6
然後,在完成每次操作前,調用InsertObjectforUndoRedo方法以對所有操作提供Undo/Redo支持。在用戶界面上點擊Undo時,只需調用UndoRedo類的Undo方法,而在用戶界面上點擊Redo時,只需調用UndoRedo類的redo方法。