2009-11-28 80 views
6

我讀在article撤消/恢復與不可改變的對象

不可變對象下面特別 方便用於實現某些共同 成語如撤消/重做,可中止 交易。以撤消爲例。 A 用於實現撤銷 的常用技術是保持一堆對象,該對象以某種方式知道如何以反向方式運行每個命令 (所謂的「命令 模式」)。然而,弄清楚如何 反向運行一個命令可以是 棘手。更簡單的技術是在連續的命令之間維護表示系統 的狀態的不可變對象堆棧 。然後, 撤消命令,你只需恢復 到以前的系統狀態(和 可能存儲在 重做堆棧中的當前狀態)。

不管怎樣,文章並沒有展示一個很好的實例,說明如何使用不可變對象來實現「撤消」操作。例如...從Gmail收件箱中刪除10封電子郵件。一旦你這樣做,它有一個撤消選項。在這方面,不可變對象將如何提供幫助?

回答

6

不可變對象將保存系統的整個狀態,因此在這種情況下,您將擁有包含原始收件箱的對象A,然後包含收件箱幷包含十封電子郵件的對象B被刪除,效果)從B指向A的指針,表示如果您執行一個「撤消」操作,則停止使用B作爲系統狀態,並開始使用A代替。

然而,Gmail收件箱都過於龐大使用這種技術。您可以將它用於實際可以存儲在相當少量內存中的文檔,以便您可以保留其中的很多文檔以進行多級撤消。

如果您想保留10個撤消級別,只需保留兩個不可變的對象(一個是當前的,一個是從十個「撤消」前的)和一個已應用的命令列表它們之間。

做一個「撤銷」,重新執行所有,但最後一個命令對象,用它作爲新的當前對象,並刪除最後一個命令(或將其保存爲「重做」的對象)。每次執行新操作時,都會更新當前對象,將相關的命令添加到列表中,然後(如果列表的長度超過十個命令),則從撤消列表的起始處對對象執行第一個命令並扔掉列表上的第一個命令。

你可以做其他各種的檢查點系統,以及涉及可變數量的系統的完整表述的,以及命令它們之間的可變數目。但是,它越來越遠離你引用的原始思想,變得越來越像一個典型的可變系統。但是,它確實避免了使命令始終可逆的問題;你只需要將Commands應用到一個對象而不是反向。

SVN和其它版本控制系統是有效的撤銷和 - 重做的盤狀或基於網絡的形式。

+3

「Gmail收件箱太大而無法使用此技術」。伊什。如果實際消息是單獨的對象,並且兩個不同的收件箱對象引用相同的消息,則收件箱只是一個列表,您可能可以這樣做。關於不可變對象的另一件好事是對象可以像這樣安全地共享資源。使用可變對象時,您可能不得不擔心對另一箇中出現錯誤的變化。 – 2009-11-28 18:03:54

+1

這是一個很好的觀點。我注意到,對於GMail帳戶,適當的不可變對象將是每個標籤的標籤列表和電子郵件對象的關聯列表;這比整個存檔小得多,但比收件箱郵件列表大得多。 – jprete 2009-11-30 18:49:53