1. 程式人生 > >面向物件設計模式之---備忘錄模式(Memento Pattern)

面向物件設計模式之---備忘錄模式(Memento Pattern)

今天要向大家介紹的模式是備忘錄模式,有時又稱作快照模式。

這個備忘錄模式一個典型的應用場景就是遊戲存檔。有時候為了打Boss,沒有成功,反而被Boss打死了,這個時候就需要利用我們之前的存檔回到最接近Boss的那一關再繼續。

備忘錄模式的定義如下:

在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在改物件之外儲存這個狀態。這樣以後就可以將該物件恢復到原先儲存的狀態。——《大話設計模式》

從這個定義我們不難看出,備忘錄模式最大的一個特點就是將某一個物件的狀態儲存到了這個物件的外部,而不是在客戶端頻繁呼叫get和set方法,這樣,就減輕了客戶端的負擔,同時對資料提供了更好的遮蔽性

備忘錄模式的UML類圖如下:

Originator類是一個發起人,就好比遊戲中的某一個場景(Scene),它除了自己的屬性之外還有兩個方法,一個是CreateMemento方法,用於建立備忘錄/快照,還有一個是setMemento方法,用於恢復備忘錄/快照。

Memento類就是備忘錄模式的核心,備忘錄類(或者稱快照類)了,這個類中儲存了我們需要Originator存檔的屬性,並提供get方法。

Caretaker類是管理者,用於管理備忘錄,它維護Memento類物件,並提供其get和set方法,它並不能Memento類內部成員。(管理者嘛,重點在維護,而不需要知道其中的奧祕~)

值得一提的是,有時候我們並不一定要在備忘錄中儲存一個類物件的全部內容,只需儲存部分,這個模式同樣可以勝任~

下面將遊戲存檔的場景用備忘錄模式模擬出來:
UML類圖:

其中,GameRole類就是Originator,Administrator就是Caretaker,Memento類與上邊對應。
轉換成程式碼如下:

import java.util.*;
//遊戲角色(發起人類)
class GameRole
{
  //角色名稱
  private String name;
  //角色力量
  private double power;
  //角色血量
  private
double blood; public GameRole(String name , double power , double blood) { this.name = name; this.power = power; this.blood = blood; } //打Boss方法,假設打不過Boss,血量將為0 public void fight() { System.out.println("=====Start Fifhting====="); this.blood = 0; } public String toString() { return "Role Name:"+this.name+"\n Role Power:"+this.power+"\n Role Blood:"+blood; } //存檔方法,這裡我們只需要對血量進行存檔 public Memento saveStatus() { return new Memento(this.blood); } //恢復存檔方法 public void setMemento(Memento snapshot) { System.out.println("=====Recovering...====="); this.blood = snapshot.getBlood(); } } //備忘錄類 class Memento { private double blood; public Memento(double blood) { this.blood = blood; } public double getBlood() { return this.blood; } } //管理者類 class Administrator { private Memento memento; public void setMemento(Memento snapshot) { this.memento = snapshot; } public Memento getMemento() { return this.memento; } } public class Main { public static void main(String args[]) { GameRole gr = new GameRole("XX",100,100); System.out.println(gr); Administrator admin = new Administrator(); admin.setMemento(gr.saveStatus()); gr.fight(); System.out.println(gr); gr.setMemento(admin.getMemento()); System.out.println(gr); } }