第三遍选拔设计格局的记挂(备忘录形式)

  我们公司有个很牛逼的女生,是我们项目组的核心人物之一,一般我有啥不懂的就问她,就在昨天我们讨论一件关于缓存的事情,我觉得在类中,用static定义的引用变量就是缓存(因为在以前的公司就这么叫),而她认为这并不是,这个只是存在内存里的,这只是一个成员变量,所以他觉得只能叫变量,牛逼的大佬们你们觉得叫什么呢?

第二次使用设计模式的思想(备忘录模式),设计模式备忘录

  我们公司有个很牛逼的女生,是我们项目组的核心人物之一,一般我有啥不懂的就问她,就在昨天我们讨论一件关于缓存的事情,我觉得在类中,用static定义的引用变量就是缓存(因为在以前的公司就这么叫),而她认为这并不是,这个只是存在内存里的,这只是一个成员变量,所以他觉得只能叫变量,牛逼的大佬们你们觉得叫什么呢?

  闲话不多说,咱先看代码:

  需求:因为客户反应,每次在页面删除或者编辑的时候,总是跳到起始页面,不能返回到他们操作前的页面上去,所以希望有一个功能可以让我在当前页面做的任意操作,只要不关闭这个页面的情况下,都保留查询条件和页数,跟操作前一样。

  思路:这还用想,备忘录模式走起啊!!

  代码:

  private static Map<String,Object> map = new HashMap<String,Object>();//定义一个备忘录
  
public void remenber(OdsXsXscb odsXsXscb){//截取使用备忘录代码

  String flag = request.getParameter("search");//如果查询进来的flag就有值否则为空

if(odsXsXscb.getId()==null&&flag==null){//如果不是查询进来的
   OdsXsXscb param = (OdsXsXscb) map.get(ses.getId());//从备忘录中取值
   if(param == null){//如果备忘录中没有值
      odsXsXscb.setException("1");//给个默认的搜索条件的值
   }else{//如果有值
      odsXsXscb = param;//将备忘录中的值取出来给与参数
   }
}else{//如果是查询进来的则保存入备忘录后不做任何操作
   map.put(ses.getId(),odsXsXscb);
}
}

@RequestMapping(value = "clear")
public void crearParam(HttpSession ses){
   map.remove(ses.getId());//如果关闭窗口则移除备忘录记录
}

我觉得这个模式使用后好方便,本来的想法是再删除的时候或者是修改的时候,都把数据拼接到地址后面,然后通过搜索条件用用input标签接收这个数据,然后又传入到后台,传值传的会想死。。
自从用了备忘录模式,大家都说好,连一直否定我的这位小姐姐,也表扬我思路清晰,
http://www.bkjia.com/cjjc/1312913.htmlwww.bkjia.comtruehttp://www.bkjia.com/cjjc/1312913.htmlTechArticle第二次使用设计模式的思想(备忘录模式),设计模式备忘录 我们公司有个很牛逼的女生,是我们项目组的核心人物之一,一般我有啥不懂...

备忘录模式

备忘录模式是一种行为型模式,作用是将对象的内部状态保存下来,在必要的时候恢复。备忘录模式可以用于游戏存档恢复、文件的历史记录等场合。

备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

  闲话不多说,咱先看代码:

图片 1

下面是一个简单的代码例子。首先是文档管理器,用于保存文档的状态。

图片 2

  需求:因为客户反应,每次在页面删除或者编辑的时候,总是跳到起始页面,不能返回到他们操作前的页面上去,所以希望有一个功能可以让我在当前页面做的任意操作,只要不关闭这个页面的情况下,都保留查询条件和页数,跟操作前一样。

备忘录模式UML.png

public class DocumentManager {
    private Map<Integer, String> map = new HashMap<>();

    public void saveDocument(int id, String content) {
        map.put(id, content);
    }

    public String loadDocument(int id) {
        return map.get(id);
    }

}

  Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的那些状态。Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。这当中要保存的细节给封装在了Memento中,那一天要更改保存的细节也不用影响客户端了。

  思路:这还用想,备忘录模式走起啊!!

class Originator{
    private int stateA = 0;
    private int stateB = 0;
    private int stateC = 0;

    public Memoto createMemoto(){
        Memoto memoto = new Memoto();
        memoto.setStateA(stateA);
        memoto.setStateB(stateB);
        memoto.setStateC(stateC);
    }

    public void restore(Memoto memoto){
        this.stateA = memoto.getStateA();
        this.stateB = memoto.getStateB();
        this.stateC = memoto.getStateC();
    }

    public void change(){
        stateA = 1;
        stateB = 2;
        stateC = 3;
    }

    public void showData(){
        System.out.println(stateA+"=="+stateB+"=="+stateC);
    }

}

然后是文档类,它利用文档管理器来保存文档的状态,并在必要的时候恢复到上个状态。

  代码基本模板

  代码:

原始类

public class Document {
    private String content;
    private DocumentManager documentManager = new DocumentManager();
    private int editCount = 0;
    private int autosaveId = 0;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        editCount++;
    }

    public Document(String content) {

        this.content = content;
    }

    public void save(int id) {
        documentManager.saveDocument(id, content);
    }

    public void autosave() {
        autosaveId = editCount;
        documentManager.saveDocument(editCount, content);
    }

    public void load(int id) {
        content = documentManager.loadDocument(id);
    }


    public void autoload() {
        content = documentManager.loadDocument(autosaveId);
    }

}
#include <iostream>

using namespace std;
//备忘录(Memento)类
class Memento
{
private:
    string m_state;
public:
    Memento(string state):m_state(state)
    {
    }
    string getState()
    {
        return this->m_state;
    }
};
//发起人(Originator)类
class Originator
{
private:
    string m_state;
public:
    void setState(string state)
    {
        this->m_state=state;
    }
    string getState()
    {
        return this->m_state;
    }
    //创建备忘录,将当前需要保存的信息导入并实例化一个Memento对象
    Memento *CreateMemento()
    {
        return (new Memento(this->m_state));
    }
    //恢复备忘录,将Memento导入并将相关数据恢复
    void SetMemento(Memento *memento)
    {
        this->m_state=memento->getState();
    }
    void Show()
    {
        cout << "State=" << this->m_state << endl;
    }
};
//管理者(Caretaker)类
class Caretaker
{
private:
    Memento *m_memento;
public:
    //设置备忘录
    void setMemento(Memento *memento)
    {
        this->m_memento=memento;
    }
    //得到备忘录
    Memento *getMemento()
    {
        return this->m_memento;
    }
};
int main()
{
    Originator *O=new Originator();
    O->setState("On");
    O->Show();
    Caretaker *c=new Caretaker();
    c->setMemento(O->CreateMemento());
    O->setState("Off");
    O->Show();
    O->SetMemento(c->getMemento());
    O->Show();
    return 0;
}
  private static Map<String,Object> map = new HashMap<String,Object>();//定义一个备忘录
  
public void remenber(OdsXsXscb odsXsXscb){//截取使用备忘录代码

  String flag = request.getParameter;//如果查询进来的flag就有值否则为空

if(odsXsXscb.getId()==null&&flag==null){//如果不是查询进来的
   OdsXsXscb param = (OdsXsXscb) map.get(ses.getId;//从备忘录中取值
   if(param == null){//如果备忘录中没有值
      odsXsXscb.setException;//给个默认的搜索条件的值
   }else{//如果有值
      odsXsXscb = param;//将备忘录中的值取出来给与参数
   }
}else{//如果是查询进来的则保存入备忘录后不做任何操作
   map.put(ses.getId(),odsXsXscb);
}
}

@RequestMapping(value = "clear")
public void crearParam(HttpSession ses){
   map.remove(ses.getId;//如果关闭窗口则移除备忘录记录
}

我觉得这个模式使用后好方便,本来的想法是再删除的时候或者是修改的时候,都把数据拼接到地址后面,然后通过搜索条件用用input标签接收这个数据,然后又传入到后台,传值传的会想死。。
自从用了备忘录模式,大家都说好,连一直否定我的这位小姐姐,也表扬我思路清晰,😊
class Memoto{
    private int stateA;
    private int stateB;
    private int stateC;

    public int getStateA(){
        return this.stateA;
    }
    public int getStateB(){
        return this.stateB;
    }
    public int getStateC(){
        return this.stateC;
    }
    public void setStateA(int a){
        this.stateA = a;
    }
    public void setStateB(int b){
        this.stateB = b;
    }
    public void setStateC(int c){
        this.stateC = c;
    }
}   

我们可以看到,在修改了文档内容之后,只要重新加载,就可以返回文档的上一个状态。

备忘录所用场合:Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来保存可撤销操作的状态。有时一些对象的内部信息必须保存在对象以外的地方,但是必须要有对象自己读取,这时,使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。其实最大的作用是在当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

数据bean类

    public void run() {
        Document document = new Document("content");
        document.setContent("content1");
        document.autosave();

        document.setContent("content2");
        document.autoload();
        System.out.println("上次结果:" + document.getContent());
    }

 

class Caretaker{
    Memoto memoto;
    public Memoto restoreMemoto(){
        return this.memoto;//恢复数据
    }

    public void storeMemoto(Memoto memoto){
        this.memoto = memoto;
    }
}

游戏进度备忘

备忘录对象,管理Memoto对象

图片 3

class Cliten{
    public static void main(String args[]){
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        originator.showData();//原始数据为 0 0 0 
        originator.change();//改变之后为 1 2 3
        caretaker.storeMemoto(originator.createMemoto());//存储状态
        //模拟下次登录之后 重新开始
        Originator originatorNew = new Originator();    
        originatorNew.restore(caretaker.restoreMemoto());
        originatorNew.showData();//数据为 1 2 3
    }
}
#include <iostream>

using namespace std;
class RoleStateMemento
{
 private:
    int m_vit;
    int m_atk;
    int m_def;
 public:
    RoleStateMemento(int vit,int atk,int def)
    {
        this->m_vit=vit;
        this->m_atk=atk;
        this->m_def=def;
    }
    int getVit()
    {
        return this->m_vit;
    }
    int getAtk()
    {
        return this->m_atk;
    }
    int getDef()
    {
        return this->m_def;
    }
};
class GameRoles
{
private:
    int m_vit;
    int m_atk;
    int m_def;
public:
    RoleStateMemento *SaveState()
    {
        return (new RoleStateMemento(this->m_vit,this->m_atk,this->m_def));
    }
    void RecoveryState(RoleStateMemento *memento)
    {
        this->m_vit=memento->getVit();
        this->m_atk=memento->getAtk();
        this->m_def=memento->getDef();
    }
    void GetInitState()
    {
        this->m_vit=100;
        this->m_atk=100;
        this->m_def=100;
    }
    void Fight()
    {
        this->m_vit=0;
        this->m_atk=0;
        this->m_def=0;
    }
    void StateDisplay()
    {
        cout << "角色当前状态:" << endl;
        cout << "体力:" << this->m_vit << endl;
        cout << "攻击力:" << this->m_atk << endl;
        cout << "防御力:" << this->m_def << endl;
    }
};
class RoleStateCaretaker
{
private:
    RoleStateMemento *m_memento;
public:
    void SetMemento(RoleStateMemento *memento)
    {
        this->m_memento=memento;
    }
    RoleStateMemento *GetMemento()
    {
        return this->m_memento;
    }
};
int main()
{
    //大战Boss前
    GameRoles *lixiaoyao=new GameRoles();
    lixiaoyao->GetInitState();
    lixiaoyao->StateDisplay();
    //保存进度
    RoleStateCaretaker *stateAdmin=new RoleStateCaretaker();
    stateAdmin->SetMemento(lixiaoyao->SaveState());
    //大战Boss时,损耗严重
    lixiaoyao->Fight();
    lixiaoyao->StateDisplay();
    //恢复之前状态
    lixiaoyao->RecoveryState(stateAdmin->GetMemento());
    lixiaoyao->StateDisplay();
    return 0;
}

客户端模拟备忘录模式。当需要保存状态的时候将状态存入Caretaker即可。Caretaker这里只是保存最后一次变化状态,可以扩展需求做的更丰富一些。

个人总结

例子比较简单,仅仅只是备忘录模式的原型。一句话概括就是备忘录类会记住应该记住的状态,而存储与恢复状态在原始类中调用。
备忘录模式在Android源码里面例子,当界面退居后台或者由于内存不足被干翻,在这之前会调用Activity中onSaveInstanceState方法保存状态。当界面再次出现在界面上时在onRestoreInstanceState方法中获取之前保存的状态。

相关文章