程式扎記: [OO 設計模式] Gossip@DesignPattern : Behavioral - Memento 模式

標籤

2014年5月27日 星期二

[OO 設計模式] Gossip@DesignPattern : Behavioral - Memento 模式

轉載自 這裡 
前言 : 
您的使用者可以對應用程式屬性進行設定,假設應用程式相關屬性是放在Application物件中,您想要設計一個屬性備份還原功能,如果您直接在Application物件中建立備份復原機制,這會使得物件本身的職責加重,與其在物件內建立備份復原機制,不如將備份復原機制從物件中脫離出來,如此一來還有可能在別的地方重用備份復原機制

Memento 模式 : 
您可使用一個 Backup物件 來封裝想要備份的資訊,Application 會負責建立Backup物件,建立的 Backup物件 則交由一個 Recovery物件 來管理,一個可能的設計方式如下所示 : 
- Backup.java :
  1. package john.dp.memento;  
  2.   
  3. import java.util.Date;  
  4.   
  5. public class Backup {  
  6.     final String state;  
  7.     final Date date;  
  8.     Backup(String state) {  
  9.         this.state = state;  
  10.         this.date = new Date();  
  11.     }  
  12. }  

- Application.java :
  1. package john.dp.memento;  
  2.   
  3. public class Application {  
  4.     private String state = "default setting";  
  5.       
  6.     Backup backup() {  
  7.         return new Backup(state);  
  8.     }  
  9.     void recover(Backup backup) {  
  10.         this.state = backup.state;  
  11.     }  
  12.       
  13.     void setState(String state) {  
  14.         this.state = state;  
  15.     }  
  16.     String getState() {  
  17.         return state;  
  18.     }  
  19. }  

- Recovery.java :
  1. package john.dp.memento;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6.   
  7. public class Recovery {  
  8.     private List backups = new ArrayList();  
  9.     void add(Backup backup) {  
  10.         backups.add(backup);  
  11.     }  
  12.     Backup retrieve(Date date) {  
  13.         for(Backup backup : backups) {  
  14.             if(backup.date.equals(date)) {  
  15.                 backups.remove(backup);  
  16.                 return backup;  
  17.             }  
  18.         }  
  19.         return null;  
  20.     }  
  21. }  

在改變 Application 狀態設定之前,您可以使用 backup() 方法對狀態進行備份,Recovery 則管理儲存 Backup 物件,之後若想要還原 Application 狀態,則可以從 Recovery 取得備份資訊進行還原。例如 : 
  1. package john.dp.memento;  
  2.   
  3. import java.util.Date;  
  4.   
  5. public class Main {  
  6.     public static void main(String[] args) {  
  7.         Application application = new Application();  
  8.         Recovery recovery = new Recovery();  
  9.           
  10.         System.out.println(application.getState());  
  11.           
  12.         Backup backup = application.backup();  // 建立備忘  
  13.         recovery.add(backup); // 加入備忘錄  
  14.           
  15.         application.setState("customer setting");  
  16.         System.out.println(application.getState());  
  17.           
  18.         Date date = backup.date; // 假設 date 是使用者自行設定所要取得的還原時間!  
  19.         application.recover(recovery.retrieve(date)); // 取得備忘來還原  
  20.         System.out.println(application.getState());  
  21.     }  
  22. }  
這是 Memento 模式 的一個例子。Memento 模式 在 Originator 中保留一個 Memento 成員,這個Memento 可以包括 Originator 的成員資訊,在外部的話, Memento 可以由一個 Caretaker 維護,每對 Originator 作一個動作,Caretaker 就保留 Originator 動作前的成員狀 態,如果以後要復原物件狀態,只要從 Caretaker 取回 Memento 物件,對 Originator 進行狀態復原. Memento 模式的 UML 類別結構圖如下所示 : 
 
圖中的 Caretaker 是用來保留原發者所創造的備忘錄物件,以供日後復原時取回,state 表示一個內部狀態,內部狀態多時,也可以將之組織為一個類別,Caretaker 維護的 Memento 可以是多個,可用來實現 Redo 與 Undo 多次的功能. 範例中 Application 即 Originator 的角色, Backup 即 Memento 的角色,Recovery 即 Caretaker 的角色.

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!