設計模式-備忘錄模式

備忘錄模式是使用一個備忘錄對象把另外一個對象內部狀態(tài)進行保存旧巾,在適當?shù)臅r候還原到某個狀態(tài)耸序。如同我們記錄某件事件,在需要回憶的時候去看下記事本鲁猩。

先來看下類圖

該模式涉及到3個角色:

  • 發(fā)起人角色:Originator坎怪,該角色包含備忘錄對象,備忘錄對象存儲了他的狀態(tài)廓握;
  • 負責人角色:Caretaker搅窿,該角色保存?zhèn)渫泴ο螅粰z查備忘錄對象內容隙券;
  • 備忘錄角色:Memento男应,將發(fā)起人對象的狀態(tài)保存起來,娱仔,保護發(fā)起人的內容不被外界訪問

寬接口與白箱

備忘錄角色對如何其他對象提供一個接口沐飘,也就是寬接口的話,那么備忘錄角色存儲的內部狀態(tài)都暴露給其他對象牲迫。這種情況導致發(fā)起人的狀態(tài)都沒看到耐朴,是破壞封裝性的,只能通過程序猿的自律盹憎。先來看下寬接口筛峭。

接下來看下代碼實現(xiàn):

public class Memento {

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

    public String getState() {
        return this.state;
    }

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

上面這個備忘錄對象提供:1、對發(fā)起人的狀態(tài)進行保存陪每;2蜒滩、可以訪問的狀態(tài)是公開的;

//發(fā)起人
public class Originator {

    private String state;
    
    //創(chuàng)建備忘錄對象來保存狀態(tài)
    public Memento createMemento(){
        return new Memento(state);
    }
    
    //從備忘錄對象里面恢復狀態(tài)
    public void restoreMemento(Memento m){
        this.state=m.getState();
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        System.out.println("當前狀態(tài):"+state);
        this.state = state;
    }
}

發(fā)起人對象利用創(chuàng)建一個新的備忘錄對象保存自己的狀態(tài)奶稠;

//負責人
public class Caretaker {

    private Memento memento;
    
    public Memento retrieveMemento(){
        return this.memento;
    }
    
    public void saveMemento(Memento m){
        this.memento=m;
    }
    
}

負責人只負責保存?zhèn)渫泴ο螅瑢渫泴ο罄锩娴膬热莶辉僮兓癖椤锌订?蛻舳说牟僮魅缦?/p>

public class Client {

    public static void main(String[] args) {
        Originator o=new Originator();
        Caretaker c=new Caretaker();
        
        //發(fā)起人狀態(tài)改變
        o.setState("Start");
        //負責人保存這個備忘錄
        c.saveMemento(o.createMemento());
        //改變狀態(tài)
        o.setState("End");
        //回到初始
        o.restoreMemento(c.retrieveMemento());

    }

}

/**  ---- result ----

當前狀態(tài):Start
當前狀態(tài):End
*/

上面就是白箱操作,很簡單画株,但是破壞了對發(fā)起人的狀態(tài)封裝辆飘;

雙重接口

所謂雙重接口就是對某一個對象提供寬接口,對另外一些類提供窄接口谓传。系統(tǒng)中可能需要將某個對象的狀態(tài)保存起來蜈项,在某個時候進行恢復,但這些狀態(tài)并不希望被外界訪問续挟,以免有外界直接修改狀態(tài)的危險紧卒,這個時候,備忘錄模式就很好的解決這個問題诗祸,他利用寬接口和窄接口來保證跑芳。

假設窄接口對所有類公開轴总,而公開類只對某一個公開,這個時候博个,我們可以把實現(xiàn)了寬接口和窄接口的具體類作為這個特殊類的內部類怀樟,寬接口的方法也可以移植到這個特殊類上,而具體類里面的方法都是私有盆佣,這樣對特殊類可以訪問所有接口往堡,其他類智能調用特殊類的某些公開方法仲吏。有點饒人忿等,畫個圖



圖1是一個基本樣子炒辉,進行演變筹我,首先寬接口方法歸屬到具體類里面池磁,變成下面這個樣子



這樣寬接口的方法還是公開的测秸,此時把具體類作為特殊類的內部類腿椎,并且优烧,把里面的方法都設置私有

這個時候的特殊類佃蚜,也就發(fā)起者代碼如下:

public class DoubleInterfaceDemo {
    
    public static void main(String[] args) {
        DoubleInterfaceDemo demo=new DoubleInterfaceDemo();
        demo.new ConcreteCLass().wide();
        demo.new ConcreteCLass().getConcrete().does();
    }

    class ConcreteCLass implements Narrow{

        @Override
        public void does() {
            System.out.println("窄接口");
        }
        
        //這個接口只能DoubleInterfaceDemo自己用了
        private void wide(){
            System.out.println("寬接口");
        }
        
        public Narrow getConcrete(){
            return (Narrow)new ConcreteCLass();
        }
        
    }
}

接下來看下黑箱的備忘錄模式庸娱,有了上面的介紹,那我們把備忘錄的具體實現(xiàn)作為內部類放到發(fā)起人對象里面

下面看下具體代碼

//發(fā)起人 加強版 黑箱
public class Originator2 {

    private String state;
    
    public Originator2() {
        
    }
    
    public MementoIF createMemento(){
        return new Memento2(this.state);
    }
    
    //內部類 備忘錄
    protected class Memento2 implements MementoIF{
        private String saveState;
        public Memento2(String saveState) {
            this.saveState=saveState;
        }
        public String getSaveState() {
            return saveState;
        }
        public void setSaveState(String saveState) {
            this.saveState = saveState;
        }
    }
    
    
    //從備忘錄對象里面恢復狀態(tài)
    public void restoreMemento(MementoIF m){
        this.state=((Memento2)m).getSaveState();
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        System.out.println("當前狀態(tài):"+state);
        this.state = state;
    }
}

負責人針對接口編程谐算,代碼如下

//負責人
public class Caretaker2 {

    private MementoIF memento;
    
    public MementoIF retrieveMemento(){
        return this.memento;
    }
    
    public void saveMemento(MementoIF m){
        this.memento=m;
    }
    
}

MementoIF這個接口是窄接口熟尉,里面可以有公共使用的方法,這里假設沒有方法洲脂。
最后測試下這個代碼

public class Client2 {

    public static void main(String[] args) {
        Originator2 o=new Originator2();
        Caretaker2 c=new Caretaker2();
        
        //發(fā)起人狀態(tài)改變
        o.setState("Start");
        //負責人保存這個備忘錄
        c.saveMemento(o.createMemento());
        //改變狀態(tài)
        o.setState("End");
        //回到初始
        o.restoreMemento(c.retrieveMemento());

    }

}

/**
最后結論和之前的一樣斤儿,但在設計上面已經(jīng)很不同

*/

有時候發(fā)起人內部信息需要保存在別的地方,但是讀取還是發(fā)起人自己恐锦,此時備忘錄模式就可以把發(fā)起人信息對外封閉起來往果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市一铅,隨后出現(xiàn)的幾起案子陕贮,更是在濱河造成了極大的恐慌,老刑警劉巖潘飘,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肮之,死亡現(xiàn)場離奇詭異,居然都是意外死亡卜录,警方通過查閱死者的電腦和手機戈擒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艰毒,“玉大人筐高,你說我怎么就攤上這事。” “怎么了凯傲?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵犬辰,是天一觀的道長。 經(jīng)常有香客問我冰单,道長幌缝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任诫欠,我火速辦了婚禮涵卵,結果婚禮上,老公的妹妹穿的比我還像新娘荒叼。我一直安慰自己轿偎,他們只是感情好,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布被廓。 她就那樣靜靜地躺著坏晦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嫁乘。 梳的紋絲不亂的頭發(fā)上昆婿,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音蜓斧,去河邊找鬼仓蛆。 笑死,一個胖子當著我的面吹牛挎春,可吹牛的內容都是我干的看疙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼直奋,長吁一口氣:“原來是場噩夢啊……” “哼能庆!你這毒婦竟也來了?” 一聲冷哼從身側響起脚线,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤相味,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后殉挽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡拓巧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年斯碌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肛度。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡傻唾,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情冠骄,我是刑警寧澤伪煤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站凛辣,受9級特大地震影響抱既,放射性物質發(fā)生泄漏。R本人自食惡果不足惜扁誓,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一防泵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝗敢,春花似錦捷泞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讶泰,卻和暖如春咏瑟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背峻厚。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工响蕴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惠桃。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓浦夷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辜王。 傳聞我的和親對象是個殘疾皇子劈狐,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容

  • 定義 備忘錄模式又叫做快照模式(Snapshot Pattern)或Token模式,是對象的行為模式呐馆。 備忘錄對象...
    步積閱讀 2,937評論 0 2
  • 在閻宏博士的《JAVA與模式》一書中開頭是這樣描述備忘錄(Memento)模式的:備忘錄模式又叫做快照模式(Sna...
    Ant_way閱讀 786評論 0 0
  • 引言 ??上一節(jié)我們說了享元模式肥缔,這節(jié)本來打算說訪問者模式的,但是太抽象汹来,而且用的不多续膳,所以本章節(jié)講備忘錄模式。 ...
    天道__閱讀 2,782評論 0 1
  • 備忘錄模式又叫做快照模式或Token模式收班,在不破壞封閉的前提下坟岔,捕獲一個對象的內部狀態(tài),并在該對象之外保存這個狀態(tài)...
    中v中閱讀 482評論 0 0
  • 備忘錄模式(Memento) 每個人都有犯錯誤的時候摔桦,都希望有種“后悔藥”能彌補自己的過失社付,讓自己重新開始,但現(xiàn)實...
    Acton_zhang閱讀 435評論 1 1