Head First 設計模式系列之二----備忘錄模式(java版)

申明:這幾天無心中關注到備忘錄模式,比較陌生回家一番參考書,只在附錄裏記錄了該模式。後來在園子裏有發現了有專門寫設計模式的博客,而且寫的也得牛逼。附上連接java

http://www.cnblogs.com/java-my-life/tag/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/,真的寫的很好。對於這個並不熟悉的模式,我也就參考他寫的,而且之後確定也會大量參考他寫的。設計模式

  在兒時確定上過遊戲室吧,筆者當時西遊記很火,咱們四個小夥準備了好些錢,打算把遊戲給打穿了。死了就接着投牌下去,接着剛纔的劇情玩下去,到最後錢完了,四我的仍是沒有打穿。其實這裏就包含着備忘錄模式,死了之後記住你當前的狀態,錢投下去了,恢復到當前狀態接着玩,而不是從第一關苦逼開始。this

1、定義和類圖spa

備忘錄對象是一人用來存儲加外一個對象內部狀態的快照對象。備忘錄模式的用意是在不破壞封裝條件下,將一個對象的狀態捕捉信,而且外部化,存儲起來,從而能夠在未來合適的時候把這個對象還原到存儲起來的狀態。備忘錄模式常與命令模式和迭代模式一同使用(這個真沒試用)。設計

Originator(發起人角色)、Memento(備忘錄角色)、Caretaker(負責人角色)3d

形象說:土豪把錢裝進箱子存進銀行rest

2、代碼實現code

Originator類對象

package design.a.memento;
/**
 * 發起人角色
 * @author team
 *
 */
public class Originator {
    private String state;
    
    //建立備忘錄角色
    public Memento createMemennto() {
        return new Memento(state);
    }
    
    //恢復到某個備忘錄對象記錄的角色
    public void restoreMemento(Memento memento) {
        this.setState(memento.getState());
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
        System.out.println("當前狀態:" + this.state);
    }
}

Memento類:blog

package design.a.memento;
/**
 * 備忘錄角色
 * 
 * @author team
 * 
 */
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
}

Caretaker類

package design.a.memento;
/**
 * 負責人角色
 * @author team
 *
 */
public class Caretaker {
    private Memento memento;
    
    public void saveMemento(Memento memento) {
        this.memento = memento;
    }
    
    public Memento retrieveMemento() {
        return this.memento;
    }
    
}

MainTest類

package design.a.memento;
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        //設置初始狀態
        originator.setState("off");
        //建立備忘錄對象(已經存了狀態),並把這個備忘錄對象存起來
        caretaker.saveMemento(originator.createMemennto());
        //更改狀態
        originator.setState("on");
        //恢復狀態
        originator.restoreMemento(caretaker.retrieveMemento());
    }
}

運行結果:

當前狀態:off
當前狀態:on
當前狀態:off

認真的人會想到這兩個問題:1.爲何建立的備忘錄對象還要保存到負責人手裏。這個負責人其實就是負責管理這個備忘錄對象的,假如後面要求說恢獲得某個狀態,這時就須要這個負責人來統一管理了。(土豪沒空保管錢裝進箱子,請了個銀行幫他保管,而不是放在家裏本身管)

2.從上面的代碼實現你會發現這個備忘錄對象是對發起人和負責人都透明的,這是多麼危險啊。(你裝進箱子多少錢,讓幫你保管錢的人知道了,說不定就會起非心,要是可以讓幫你保管錢的人連裏面裝的是什麼那多麼好啊,就給他個箱子,你來保管吧)這個在java裏面就能夠用到接口和內部類來實現。

將Memento設成Originator類的內部類,從而將Memento對象封裝在Originator裏面;在外部提供一個標識接口MementoIF給Caretaker以及其餘對象。

3、代碼實現plus

Originator類

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class Originator {
    private String state;
    
    public void setState(String state) {
        this.state = state;
        System.out.println("當前狀態:" + this.state);
    }
    
    public String getState() {
        return this.state;
    }
    
    public MementoIF createMemento() {
        return new Memento(state);
    }
    
    public void restoreMemento(MementoIF memento) {
        this.setState(((Memento)memento).getState());
    }
    
    class Memento implements MementoIF {
        private String state;
        
        private Memento(String state) {
            this.state = state;
        }
        public String getState() {
            return this.state;
        }
        
        public void setState(String state) {
            this.state = state;
        }
    }
}

MementoIF接口

package design.a.mementoPlus;
/**
 *
 * @author team
 *
 */
public interface MementoIF {

}

Caretaker類

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class Caretaker {
    private MementoIF memento;
    //備忘錄對象獲取
    public MementoIF retrieveMemento() {
        return memento;
    }
    //備忘錄賦值
    public void saveMemento(MementoIF memento){
        this.memento = memento;
    }
}

MainTest類

package design.a.mementoPlus;
/**
 * 
 * @author team
 *
 */
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        //設置初始狀態
        originator.setState("off");
        //建立備忘錄對象(已經存了狀態),並把這個備忘錄對象存起來
        caretaker.saveMemento(originator.createMemento());
        //更改狀態
        originator.setState("no");
        //恢復狀態
        originator.restoreMemento(caretaker.retrieveMemento());
        
    }
}

運行結果:

當前狀態:off
當前狀態:no
當前狀態:off

問題來了:就像上面說的問題1負責人哪能就幹這麼簡單的事,(土豪錢多要保存多個箱子,讓他隨時取出他想要的箱子)咱們就須要存儲多個狀態

備忘錄模式能夠將發起人對象的狀態存儲到備忘錄對象裏面,備忘錄模式能夠將發起人對象恢復到備忘錄對象所存儲的某一個檢查點上

4、代碼實現plus++

Originator類

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Originator {
    private List<String> states;
    
    public Originator() {
        states = new ArrayList<String>();
    }
    //建立備忘錄
    public Memento createMemento() {
        return new Memento(states);
    }
    //恢復到備忘錄記錄的狀態
    public void restoreMemento(Memento memento) {
        states = memento.getStates();
    }
    //狀態賦值
    public void setState(String state) {
        states.add(state);
    }
    //打印狀態
    public void printStates() {
        for(String state : states) {
            System.out.println(state);
        }
    }
}

Memento類

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Memento {
    private List<String> states;
    
    public Memento(List<String> states) {
        this.states = new ArrayList<String>(states);
    }

    public List<String> getStates() {
        return states;
    }

}

Caretaker類

package design.a.mementoPlus2;
import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author team
 *
 */
public class Caretaker {
    private Originator originator;
    
    private List<Memento> mementos = new ArrayList<Memento>();
    
    public Caretaker(Originator originator) {
        this.originator = originator;
    }
    //建立備忘錄
    public void createMemento() {
        Memento memento = originator.createMemento();
        mementos.add(memento);
    }
    //恢復到備忘錄記錄的狀態
    public void restoreMemento(int index) {
        Memento memento = mementos.get(index);
        originator.restoreMemento(memento);
    }
    
}

MainTest類

package design.a.mementoPlus2;
/**
 * 
 * @author team
 *
 */
public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();

        Caretaker caretaker = new Caretaker(originator);

        originator.setState("state one");

        caretaker.createMemento();

        originator.setState("state two");

        caretaker.createMemento();

        originator.setState("state three");

        caretaker.createMemento();
        
        originator.setState("state four");

        caretaker.createMemento();
        
        System.out.println("打印當前全部狀態");
        originator.printStates();
        
        caretaker.restoreMemento(2);
        
        System.out.println("打印恢復後的全部狀態");
        originator.printStates();
        
        
    }
}

注意剛纔寫Memento備忘錄時開始:this.states = states;形成運行一直出錯,states是個List是對象引用,因此return new Memento(states);每次產生的Memento

裏面的states都是指向同一個的。應該寫成this.states = new ArrayList<String>(states);

運行結果

打印當前全部狀態
state one
state two
state three
state four
打印恢復後的全部狀態
state one
state two
state three

所謂「自述歷史」模式(History-On-Self Pattern)實際上就是備忘錄模式的一個變種。在備忘錄模式中,發起人(Originator)角色、負責人(Caretaker)角色和備忘錄 (Memento)角色都是獨立的角色。雖然在實現上備忘錄類能夠成爲發起人類的內部成員類,可是備忘錄類仍然保持做爲一個角色的獨立意義。在「自述歷 史」模式裏面,發起人角色本身兼任負責人角色。

5、代碼實現plus++++

MementoIF接口

package design.a.mementoPlus3;
/**
 * 
 * @author team
 *
 */
public interface MementoIF {

}

Originator類

package design.a.mementoPlus3;
/**
 * 
 * @author team
 * 
 */
public class Originator {
    public String state;

    public void changeState(String state) {
        this.state = state;
        System.out.println("狀態改成:" + state);
    }

    public Memento createMemento() {
        return new Memento(this);
    }

    public void restoreMemento(MementoIF memento) {
        Memento memento2 = (Memento) memento;
        changeState(memento2.state);
    }

    private class Memento implements MementoIF {
        private String state;

        private Memento(Originator originator) {
            this.state = originator.state;
        }
    }
}

MainTest類

package design.a.mementoPlus3;

public class MainTest {
    public static void main(String[] args) {
        Originator originator = new Originator();
        
        originator.changeState("state one");
        
        MementoIF memento = originator.createMemento();
        
        originator.changeState("state two");
        
        originator.restoreMemento(memento);
    }
}

運行結果:

狀態改成:state one
狀態改成:state two
狀態改成:state one

因爲在實際中尚未應用過備忘錄模式,後面可能還會再寫一篇應用的。

相關文章
相關標籤/搜索