詳解Objective-C設計模式編程中對備忘錄模式的運用_IOS

來源:互聯網
上載者:User

基本理解
這個模式有三個關鍵角色:原發器(Originator)、備忘錄(Memento)、看管人(caretaker)。三者的基本關係是:原發器建立一個包含其狀態的備忘錄,並傳給看管人。看管人不知道如何與備忘錄互動,但會把備忘錄放在一個安全之處保管好。
備忘錄(Memento):在 不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外儲存這個狀態。這樣以後就可以將該對象回複到原先儲存的狀態。
Originator(發起人):負責建立一個備忘錄,用以記錄當前時刻它的內部狀態,並且可使用恢複備忘錄內部狀態。Originator可根據需要決定Memento儲存Originator的哪些內部狀態。
Memento(備忘錄):負責儲存Originator對象的內部狀態,並可防止Originator以外的其他對象訪問備忘錄。備忘錄有兩個介面,CareTaker
只能看到備忘錄的窄介面,它只能將備忘錄傳給其他對象。originator能夠看到一個寬介面,允許它訪問返回到先前狀態所需的所有資料。
Caretaker(管理者):負責儲存好備忘錄,不能對備忘錄的內容進行操作或檢查。
就是把要儲存的細節給封裝在了Memento中,哪一天要更改儲存的細節也不用影響用戶端了。

備忘錄使用場合
備忘錄模式比較適用於功能比較複雜的,但需要維護或記錄屬性曆史的類,或者需要儲存的屬性只是眾多屬性中的一小部分時,Orignator可以根據儲存的Memento資訊還原到前一狀態。
如果在某個系統中使用命令模式時,需要實現命令的撤銷功能,那麼命令模式可以使用備忘錄模式來儲存撤銷操作的狀態。有的時候一些對象的內部資訊必須要儲存在對象以外的地方,但是必須要由對象自己讀取,這時,使用備忘錄可以把複雜的對象內部資訊對其他的對象屏蔽起來。
用於擷取狀態的介面會暴露實現介面,需要將其屏蔽起來。
它一般應用於遊戲、文文書處理程式的設計中,這種程式需要儲存當前內容相關的複雜狀態的快照並在以後恢複處理。

作用
當角色的狀態改變時,有可能這個狀態無效,這時候就可以使用暫時儲存起來的備忘錄將狀態複原。
Cocoa Touch架構中的備忘錄模式
Cocoa Touch架構在歸檔、屬性列表序列化和核心資料採用了備忘錄模式。
Cocoa的歸檔是對對象以及其屬性還有同其他對象間的關係進行編碼,形成一個文檔,該文檔既可儲存與檔案系統中,也可在進程或網路間傳送。對象與其他對象的關係被看做對象圖的網路。
歸檔過程把對象儲存為一種與架構無關的位元組流,保持對象的標識以及對象之間的關係。對象的類型也同資料一起儲存。從位元組流解碼出來的對象通常用於對象編碼時相同的類進行執行個體化。使用NSCoder的具體類NSKeyedArchiver和NSKeyedUnarchiver,使用基於鍵的歸檔技術,被編碼與解碼的對象必須遵守NSCoding協議並實現以下方法:

複製代碼 代碼如下:

-(id)initWithCoder:(NSCoder *)coder;
-(void)encodeWithCoder:(NSCoder *)coder;

執行個體
添加下面兩個方法到 ViewController.m 檔案:

複製代碼 代碼如下:

- (void)saveCurrentState
{
    // 當使用者退出應用之後再重新開啟,他想要跟他之前退出時一樣的狀態
    // 退出應用,這個時候我們需要做的是把當前顯示的專輯儲存下來
    // 因為只有一小片資訊,我們可用 NSUserDefaults 來儲存資訊
    [[NSUserDefaults standardUserDefaults] setInteger:currentAlbumIndex forKey:@“currentAlbumIndex”];
}

- (void)loadPreviousState
{
    currentAlbumIndex = [[NSUserDefaults standardUserDefaults] integerForKey@“currentAlbumIndex”];
    [self showDataForAlbumAtIndex:currentAlbumIndex];
}


saveCurrentState 儲存當前專輯的索引到 NSUserDefaults ─ NSUserDefaults 是一個標準資料存放區,iOS 用來專門存放程式設定和資料。

loadPreviousState 載入這之前儲存的專輯索引。這不是備忘錄模式的全部,不過你已經達到目的了。

現在,在 ViewController.m 裡,滾動視圖初始化之前,在 viewDidLoad 裡添加下面一行:

複製代碼 代碼如下:

[self loadPreviousState];

當程式啟動的時候載入上一次儲存的狀態。但是你在哪裡儲存程式的目前狀態呢?你需要使用通知來做這樣的事情。當程式進入後台時,iOS 會發送一個 UIApplicationDidEnterBackgroundNotification 通知。你可利用這個通知調用 saveCurrentState。就這麼方便?

在 viewDidLoad: 最後面添加下面一行

複製代碼 代碼如下:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCurrentState) name:UIApplicationDidEnterBackgroundNotification object:nil];

現在,當你的 app 進入後台運行後,ViewController 會自動調用 saveCurrentState 儲存當前的狀態。

現在,添加下面代碼:

複製代碼 代碼如下:

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

這裡是確保當 ViewController 被釋放時,移除類的 Observer。

構建和運行你的 app,點擊到一個專輯,用 Command+Shift+H(如果你使用的是模擬器的話) 將程式在後台運行,然後關掉 app。重啟 app,檢查之前選擇的專輯是不是置中顯示:

專輯資料看起來是對的,但是正確的專輯封面確沒有置中,哪出問題了?

這就是可選方法 initialViewIndexForHorizontalScroller 的用處!因為這個方法沒有被委託執行,ViewController 在這種情況下總是會顯示預設的第一個專輯封面。

修複這個問題,在 ViewController.m 中添加如下代碼:

複製代碼 代碼如下:

- (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller *)scroller
{
    return currentAlbumIndex;
}

現在 HorizontalScroller 的第一個視圖總是會被設定成 currentAlbumIndex 索引的圖片。這種方法能夠確保你的 app 有一個非常棒的使用者體驗,並且它是可恢複的。

重新運行你的 app,滾動專輯封面,關閉 app,然後重啟確保問題已經得到解決:

如果你查看 PersistencyManger 的初始化方法,你會注意到專輯的資料是一種寫入程式碼,PersistencyManger 每次建立,資料也會重複建立一次。有沒有一種更好的方法當專輯列表被建立的時候就儲存它們呢。那麼如何把專輯資料存放區到檔案裡呢?

一種選擇就是逐一查看 Album 的屬性,然後把它儲存在一個 plist 檔案裡,當需要它們的時候重新建立一個 Album 的執行個體。這不是最好的選擇,這需要你在每一個類雷根據不同的資料或屬性寫特定的代碼。例子,如果稍後你需要一個電影的類,裡面有一些不同的屬性,儲存和載入這些資料你就需要寫一些新的代碼。

此外,你不能在每一個類的執行個體裡儲存私人變數,因為他們是不可訪問的外部類。這就是為什麼蘋果要建立歸檔 (Archiving) 機制。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.