備忘錄模式,在工作代碼中,要麼不用,要麼經常用到。
舉個例子,程式員喜歡寫代碼,coding,coding,這個時候它的狀態是很high,但是每隔一段時間總要去上一下廁所,狀態是放鬆relax,上完測試歸來後又恢複到high的狀態,繼續coding。這個過程對於身後的老闆來說,它預設同意你離開去上廁所,他也希望你回來後恢複high的狀態繼續工作,但是你在這個過程中上廁所的這件事,他是不需要瞭解細節的,而且做為當事人你也不希望他瞭解你上廁所的細節吧,你只要回來後恢複激情high著繼續工作,老闆應該就不會挑你的刺。
這就是備忘錄模式。
本文今天就Canvas的一個save(),restore()操作分析一下,但是有一點,看完本文,如果不懂備忘錄模式的,應該還是不懂,但是canvas是android的一場大戲,說一說它的特色,對深入學習android絕對有協助。
學習備忘錄模式,通過儲存狀態,恢複狀態的內部實現,對瞭解一些莫名其妙的看上去無用其實很重要的操作有撥開雲霧見青天的作用。
1.意圖
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外儲存這個狀態,這樣以後就可以將該對象恢複到先前儲存的狀態。
熱門詞彙:標記 狀態 備忘錄 原發器
2.結構和代碼
召集人,把原發器的狀態State(全部或者部分狀態,一般是變數的值),通過CreateMemento()方法儲存起來,繼續運行後,等待合適的時機,在通過SetMemento()方法可以再次恢複到之前的狀態。在這個過程中,我們並沒有對這些狀態做任何的訪問和設定,實際上這些狀態都是私人的,對外是禁止訪問的,我們只是通過Memento對象的兩個最簡單的方法就達到了這個效果。Memento經常寫成Originator的內部類。
在Android中,Canvas有兩個方法 save()和restore()方法再做圖形變換的時候使用的非常多,因為涉及到跨語言的問題,我不好就認定這個用的是備忘錄模式,但是它的這種思想絕對是備忘錄的思想。
我們來讀一讀它原始碼的注釋吧,首先看save()儲存狀態:
public class Canvas { /** * Saves the current matrix and clip onto a private stack. Subsequent * calls to translate,scale,rotate,skew,concat or clip Rect,clipPath * will all operate as usual, but when the balancing call to restore() * is made, those calls will be forgotten, and the settings that existed * before the save() will be reinstated. */ /** *儲存當前的矩陣和剪裁到一個私人的堆棧,其實矩陣和剪裁就是當前Canvas的狀態State */ public native int save();}
再看恢複狀態restore():
public class Canvas { /** * This call balances a previous call to save(), and is used to remove all * modifications to the matrix/clip state since the last save call. It is * an error to call restore() more times than save() was called. */ /** * 移除自上次儲存操作後所做的修改,恢複到之前的狀態,因為是堆棧實現,所以pull操作不能不等於push操作,save()和restore()應該成對使用,否則恢複的狀態就很有可能是錯誤的 */ public native void restore();}
從上面的兩個方法中,它們實現了自我狀態的恢複,實際上我們只是執行了兩個沒有接觸任何內部資訊的方法,實際上這兩個方法就是在操作我們看不到的這些內部狀態資訊。
3.效果
(1).保持封裝邊界,把很複雜的原發器的內部資訊對外部其他對象隱藏起來。
(2).簡化的原發器,把狀態操作無形中轉化到客戶手裡,簡化了原發器的某些實現。
(3).也要注意注意備忘錄的管理代價。