設(shè)計(jì)模式之備忘錄模式(Memento)

概念基礎(chǔ)

  • 定義:在不破壞封裝性的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要時(shí)能將該對象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式。
  • 場景:備份,恢復(fù),工作流回退
  • 推導(dǎo)過程

1.被存儲(chǔ)的對象(假設(shè)為Student) ,提供 store,recover 方法
2.保存的對象 => 引出StudentMemenTo(深淺clone根據(jù)業(yè)務(wù))
3.需要有一個(gè)對象保存 StudentMemenTo的引用. =>引出 CareTaker
4.疑問:為什么要構(gòu)建一個(gè)一樣的新類,而不是直接返回一個(gè)新的clone對象 Student

  • 窄接口:負(fù)責(zé)人(Caretaker)對象(和其他除發(fā)起人之外的任何對象)看到的是備忘錄的窄接口(narrow interface),這個(gè)窄接口只允許它把備忘錄對象傳給其他的對象。
  • 寬接口:與負(fù)責(zé)人對象看到的窄接口相反的是,發(fā)起人對象可以看到一個(gè)寬接口(wide interface),這個(gè)寬接口允許它讀取所有的數(shù)據(jù),以便根據(jù)這些數(shù)據(jù)恢復(fù)對這個(gè)發(fā)起人對象的內(nèi)部狀態(tài)。(限制手段 內(nèi)部類+空接口,屏蔽負(fù)責(zé)人對象對備忘錄的訪問,僅僅作為一個(gè)傳遞作用)

Session 會(huì)話,就可以被當(dāng)做負(fù)責(zé)人對象來使用, Spring 工作流中,有應(yīng)用

public interface StateManageableMessageContext extends MessageContext {
    Serializable <STRONG>createMessagesMemento</STRONG>();

    void<STRONG> restoreMessages</STRONG>(Serializable var1);

    void<STRONG> setMessageSource</STRONG>(MessageSource var1);
}
image.png

優(yōu)化,黑盒模式

  • 空接口+內(nèi)部類 => 屏蔽看守者對備忘錄的操作.(最少知道原則)
  • 發(fā)起人角色
package com.dzq.memento.dark;

public class Student {
    private int age ;
    private String name;
    /*保存*/
    public StudentMementoIf store(){
        return new StudentMemento(this);
    }
    /*恢復(fù)*/
    public void recover(StudentMementoIf stu){
        /*強(qiáng)制轉(zhuǎn)化為備忘錄對象*/
        StudentMemento student = (StudentMemento) stu;
        this.age = student.age;
        this.name = student.name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    /*內(nèi)部類,僅僅Student本身能夠訪問*/
    protected class StudentMemento implements StudentMementoIf{
        private int age ;
        private String name;

        public StudentMemento(Student student) {
            this.age = student.age;
            this.name = student.name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }


}

  • 看守人實(shí)現(xiàn)(無法調(diào)用備忘錄對象的方法)
package com.dzq.memento.dark;

import com.dzq.memento.PersonMemento;

import java.util.Vector;

/*看守人*/
public class CareTaker {
    private StudentMementoIf studentMementoIf;

    public StudentMementoIf getStudentMementoIf() {
        return studentMementoIf;
    }

    public void setStudentMementoIf(StudentMementoIf studentMementoIf) {
        this.studentMementoIf = studentMementoIf;
    }
}

  • 備忘錄實(shí)現(xiàn)的空接口
package com.dzq.memento.dark;

/*空接口,用于屏蔽管理者對備份類的可見性*/
public interface StudentMementoIf {
}

優(yōu)化二

  • 以上僅僅是簡單狀態(tài)屬性,并且只能恢復(fù)到上一個(gè)節(jié)點(diǎn).如果需要將狀態(tài)恢復(fù)到第N次節(jié)點(diǎn),如何實(shí)現(xiàn)?
  • 數(shù)組 + index ,可以做到恢復(fù)至某個(gè)具體的版本.
package com.dzq.memento.multi_check;

import java.util.Vector;
/**
 * 常見的軟件系統(tǒng)往往存儲(chǔ)不止一個(gè)狀態(tài),而是需要存儲(chǔ)多個(gè)狀態(tài)或者叫做有多個(gè)檢查點(diǎn)
* */
public class Message {
    private Vector states;//核心  數(shù)組 + current_index
    private int index;

    public Vector getStates() {
        return states;
    }

    public void setStates(Vector states) {
        this.states = states;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容