軟件設計模式學習(二十二)備忘錄模式


備忘錄模式提供了一種對象狀態的撤銷實現機制,當系統中某一對象須要恢復到某一歷史狀態時可使用備忘錄模式來進行設計java


模式動機

人人都有後悔的時候,在軟件使用過程當中不免會出現一些誤操做,如不當心刪除了某些文字或圖片,數據填入錯誤等,對於這些誤操做,須要提供一種後悔藥機制,讓系統能夠回到誤操做前的狀態,這就是備忘錄模式的模式動機函數


模式定義

在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣能夠在之後將對象恢復到原先保存的狀態。備忘錄模式是一種對象行爲型模式,其別名爲 Token測試


模式結構

  1. Originator(原發器)this

    原發器能夠建立一個備忘錄,並存儲它的當前內部狀態,也可使用備忘錄來恢復其內部狀態。通常將須要保存內部狀態的類設計爲原發器。設計

  2. Memento(備忘錄)rest

    存儲原發器的內部狀態,根據原發器來決定保存哪些內部狀態。須要注意的是,除了原發器自己與負責人以外,備忘錄對象不能直接供其餘類使用。code

  3. Caretaker(負責人)對象

    負責人又稱管理者,它負責保存備忘錄,可是不能對備忘錄的內容進行操做或檢查。blog


模式分析

前面已經說了,備忘錄模式就是用來吃後悔藥的,理解起來並不難,關鍵在於如何設計備忘錄類和負責人類。接口

備忘錄中存儲的是原發器的中間狀態,所以須要防止原發器之外的其餘對象訪問備忘錄。也不能在備忘錄對象以外保存原發器狀態,若是暴露其內部狀態將違反封裝的原則。

爲了實現對備忘錄對象的封裝,須要對備忘錄的調用進行控制。對於原發器而言,它能夠調用備忘錄的全部信息,容許原發器訪問先前狀態的全部數據。對於負責人而言,只負責備忘錄的保存並將備忘錄傳遞給其餘對象。對於其餘對象而言,只須要從負責人處取出備忘錄對象並將原發器對象的狀態恢復,而無須關心備忘錄的保存狀態。

下面經過一個實例來進一步理解備忘錄模式。


模式實例

某系統提供了用戶信息操做模塊,用戶能夠修改本身的各項信息,用戶在進行了錯誤操做後能夠恢復到操做以前的狀態。

  1. 原發器 UserInfoDTO(用戶信息類)

    package dp.memento;
    
    public class UserInfoDTO {
    
        private String account;
        private String password;
    
        public String getAccount() {
            return account;
        }
    
        public void setAccount(String account) {
            this.account = account;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    	
        //	建立一個備忘錄對象
        public Memento saveMemento() {
            return new Memento(account, password);
        }
    	
        //	根據備忘錄對象恢復原發器狀態
        public void restoreMemento(Memento memento) {
            this.account = memento.getAccount();
            this.password = memento.getPassword();
        }
    
        public void show() {
            System.out.println("Account: " + this.account);
            System.out.println("Password: " + this.getPassword());
        }
    }
  2. 備忘錄 Memento

    設計備忘錄時須要考慮到封裝性,即除了原發器類,不容許其餘類來調用其構造函數與相關方法。通常將備忘錄類和原發器類定義在同一包中來實現封裝,使用默認訪問標識符來定義備忘錄類,即保證包內可見性。

    package dp.memento;
    
    class Memento {
    
        private String account;
        private String password;
    
        public Memento(String account, String password) {
            this.account = account;
            this.password = password;
        }
    
        public String getAccount() {
            return account;
        }
    
        public void setAccount(String account) {
            this.account = account;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
  3. 負責人 Caretaker

    package dp.memento;
    
    public class Caretaker {
    
        private Memento memento;
    
        public Memento getMemento() {
            return memento;
        }
    
        public void setMemento(Memento memento) {
            this.memento = memento;
        }
    }
  4. 客戶端測試類 Client

    import dp.memento.UserInfoDTO;
    import dp.memento.Caretaker;
    
    public class Client {
    
        public static void main(String[] args) {
    
            UserInfoDTO user = new UserInfoDTO();
    		
            // 建立負責人
            Caretaker caretaker = new Caretaker();
    
            user.setAccount("zhangsan");
            user.setPassword("123456");
            System.out.println("狀態一");
            user.show();
            
    		// 保存備忘錄
            caretaker.setMemento(user.saveMemento());
            System.out.println("------------------------");
    
            user.setPassword("11111111");
            System.out.println("狀態二");
            user.show();
            System.out.println("------------------------");
    
            // 從備忘錄中恢復
            user.restoreMemento(caretaker.getMemento());
            System.out.println("回到狀態一");
            user.show();
            System.out.println("------------------------");
        }
    }
  5. 運行結果


模式優缺點

備忘錄模式優勢:

  • 提供了一種狀態恢復的實現機制,使得用戶能夠方便地回到特定的一個歷史步驟
  • 實現了信息的封裝,備忘錄只保存原發器的狀態,不會被其餘代碼修改。採用堆棧來存儲備忘錄對象能夠實現屢次撤銷操做,能夠經過在負責人中定義集合對象來存儲多個備忘錄。

備忘錄模式缺點:

  • 每保存一次對象的狀態都須要消耗內存資源,資源消耗過大

模式適用環境

在如下狀況可使用備忘錄模式:

  • 保存一個對象在某一時刻的狀態或部分狀態
  • 若是用一個接口來讓其餘對象獲得這些狀態,將會暴露對象的實現細節並破壞封裝性,一個對象不但願外界直接訪問獲得其內部狀態,經過負責人能夠間接訪問其內部狀態
相關文章
相關標籤/搜索