大话设计模式

1 备忘录模式结构图

2 对备忘录模式的一些解释

概念:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。【DP】
Origanator(发起人):负责创建一个备忘录Memento,用以记录当前时刻他的内部状态,并可以使用备忘录恢复到内部状态。Originator可以根据需要决定Memento存储Originator的哪些内部状态。
Memento(备忘录):负责存储P日过in阿投入对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许她访问返回到先前状态所需的所有数据。
Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容金星操作或者检查。
优点:把要保存的细节封装在了Memento中,哪一天要更改保存的细节也不用影响客户端了。
使用场景
  • Memento模式比较适用于功能比较复杂的,但需要维护或者记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态;
  • 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态【DP】;
  • 当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录模式将状态恢复【DP】。

3 C++源代码实现

3.1 代码结构图

3.2 C++源代码:

游戏角色类RoleOriginator.h
#ifndef _ROLE_ORIGINATOR_H_
#define _ROLE_ORIGINATOR_H_class RoleStateMemento;class RoleOriginator
{
private:int vit;//生命力int atk;//攻击力int def;//防御力RoleStateMemento *memento;public:void setVitality(int vit);int getVitality();void setAttack(int atk);int getAttack();void setDefense(int def);int getDefense();void StateDisplay();//状态显示void GetInitState();//初始化状态void fight();//战斗之后,各项指标RoleStateMemento *SaveState();//保存角色状态void RecoveryState(RoleStateMemento *memento);//回复角色状态
};#endif

RoleOriginator.cpp

#include"RoleOriginator.h"
#include"RoleStateMemento.h"
#include<iostream>using std::cout;
using std::endl;void RoleOriginator::setVitality(int vit)
{this->vit = vit;
}
int RoleOriginator::getVitality()
{return this->vit;
}void RoleOriginator::setAttack(int atk)
{this->atk = atk;
}
int RoleOriginator::getAttack()
{return this->atk;
}void RoleOriginator::setDefense(int def)
{this->def = def;
}int RoleOriginator::getDefense()
{return this->def;
}void RoleOriginator::StateDisplay()//状态显示
{cout << "生命力:" << this->getVitality() << ";  攻击力:" << this->getAttack() << ";  防御力:" << this->getDefense() << endl;
}void RoleOriginator::GetInitState()//初始化状态
{this->atk = 100;this->vit = 100;this->def = 100;
}void RoleOriginator::fight()//战斗之后,各项指标
{this->atk = 0;this->vit = 0;this->def = 0;
}RoleStateMemento *RoleOriginator::SaveState()//保存角色状态
{return new RoleStateMemento(vit, atk, def);
}void RoleOriginator::RecoveryState(RoleStateMemento *memento)//回复角色状态
{this->atk = memento->getAttack();this->vit = memento->getVitality();this->def = memento->getDefense();
}

角色状态存储箱类RoleStateMemento.h

#ifndef _ROLE_STATE_MEMENTO_H_
#define _ROLE_STATE_MEMENTO_H_class RoleStateMemento
{
private:int vit;int atk;int def;public:RoleStateMemento(int vit, int atk, int def);void setVitality(int vit);int getVitality();void setAttack(int atk);int getAttack();void setDefense(int def);int getDefense();
};#endif

RoleStateMemento.cpp

#include"RoleStateMemento.h"RoleStateMemento::RoleStateMemento(int vit, int atk, int def)
{this->vit = vit;this->atk = atk;this->def = def;
}void RoleStateMemento::setVitality(int vit)
{this->vit = vit;
}
int RoleStateMemento::getVitality()
{return this->vit;
}void RoleStateMemento::setAttack(int atk)
{this->atk = atk;
}
int RoleStateMemento::getAttack()
{return this->atk;
}void RoleStateMemento::setDefense(int def)
{this->def = def;
}int RoleStateMemento::getDefense()
{return this->def;
}

游戏状态管理者类RoleCaretaker.h

#ifndef _ROLE_CARETAKER_H_
#define _ROLE_CARETAKER_H_#include"RoleStateMemento.h"class RoleCaretaker
{
private:RoleStateMemento *memento;public:void setMemento(RoleStateMemento *memento){this->memento = memento;}RoleStateMemento *getMemento(){return this->memento;}
};#endif

客户端Client.cpp

#include"RoleOriginator.h"
#include"RoleStateMemento.h"
#include"RoleCaretaker.h"
#include<iostream>using std::cout;
using std::endl;int main()
{RoleOriginator *role = new RoleOriginator();role->GetInitState();//游戏初始化role->StateDisplay();RoleCaretaker *save = new RoleCaretaker();save->setMemento(role->SaveState());//保存游戏进度role->fight();//激战之后role->StateDisplay();role->RecoveryState(save->getMemento());//恢复游戏进度role->StateDisplay();delete role;delete save;system("pause");return 0;
}

运行结果:

生命力:100;  攻击力:100;  防御力:100
生命力:0;  攻击力:0;  防御力:0
生命力:100;  攻击力:100;  防御力:100
请按任意键继续. . .

以下内容引自<http://blog.csdn.net/zhengzhb/article/details/7697549>,转载请注明出处!!!



卡奴达摩----备忘录模式

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

类型:行为类

类图
我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态。比如,我们使用Eclipse进行编程时,假如编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回。这时我们便可以使用备忘录模式来实现。

备忘录模式的结构

  • 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
  • 备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
  • 管理角色:对备忘录进行管理,保存和提供备忘录。

通用代码实现

class Originator {private String state = "";public String getState() {return state;}public void setState(String state) {this.state = state;}public Memento createMemento(){return new Memento(this.state);}public void restoreMemento(Memento memento){this.setState(memento.getState());}
}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;}
}
class Caretaker {private Memento memento;public Memento getMemento(){return memento;}public void setMemento(Memento memento){this.memento = memento;}
}
public class Client {public static void main(String[] args){Originator originator = new Originator();originator.setState("状态1");System.out.println("初始状态:"+originator.getState());Caretaker caretaker = new Caretaker();caretaker.setMemento(originator.createMemento());originator.setState("状态2");System.out.println("改变后状态:"+originator.getState());originator.restoreMemento(caretaker.getMemento());System.out.println("恢复后状态:"+originator.getState());}
}

代码演示了一个单状态单备份的例子,逻辑非常简单:Originator类中的state变量需要备份,以便在需要的时候恢复;Memento类中,也有一个state变量,用来存储Originator类中state变量的临时状态;而Caretaker类就是用来管理备忘录类的,用来向备忘录对象中写入状态或者取回状态。

多状态多备份备忘录

通用代码演示的例子中,Originator类只有一个state变量需要备份,而通常情况下,发起人角色通常是一个javaBean,对象中需要备份的变量不止一个,需要备份的状态也不止一个,这就是多状态多备份备忘录。实现备忘录的方法很多,备忘录模式有很多变形和处理方式,像通用代码那样的方式一般不会用到,多数情况下的备忘录模式,是多状态多备份的。其实实现多状态多备份也很简单,最常用的方法是,我们在Memento中增加一个Map容器来存储所有的状态,在Caretaker类中同样使用一个Map容器才存储所有的备份。下面我们给出一个多状态多备份的例子:

class Originator {private String state1 = "";private String state2 = "";private String state3 = "";public String getState1() {return state1;}public void setState1(String state1) {this.state1 = state1;}public String getState2() {return state2;}public void setState2(String state2) {this.state2 = state2;}public String getState3() {return state3;}public void setState3(String state3) {this.state3 = state3;}public Memento createMemento(){return new Memento(BeanUtils.backupProp(this));}public void restoreMemento(Memento memento){BeanUtils.restoreProp(this, memento.getStateMap());}public String toString(){return "state1="+state1+"state2="+state2+"state3="+state3;}
}
class Memento {private Map<String, Object> stateMap;public Memento(Map<String, Object> map){this.stateMap = map;}public Map<String, Object> getStateMap() {return stateMap;}public void setStateMap(Map<String, Object> stateMap) {this.stateMap = stateMap;}
}
class BeanUtils {public static Map<String, Object> backupProp(Object bean){Map<String, Object> result = new HashMap<String, Object>();try{BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();for(PropertyDescriptor des: descriptors){String fieldName = des.getName();Method getter = des.getReadMethod();Object fieldValue = getter.invoke(bean, new Object[]{});if(!fieldName.equalsIgnoreCase("class")){result.put(fieldName, fieldValue);}}}catch(Exception e){e.printStackTrace();}return result;}public static void restoreProp(Object bean, Map<String, Object> propMap){try {BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();for(PropertyDescriptor des: descriptors){String fieldName = des.getName();if(propMap.containsKey(fieldName)){Method setter = des.getWriteMethod();setter.invoke(bean, new Object[]{propMap.get(fieldName)});}}} catch (Exception e) {e.printStackTrace();}}
}
class Caretaker {private Map<String, Memento> memMap = new HashMap<String, Memento>();public Memento getMemento(String index){return memMap.get(index);}public void setMemento(String index, Memento memento){this.memMap.put(index, memento);}
}
class Client {public static void main(String[] args){Originator ori = new Originator();Caretaker caretaker = new Caretaker();ori.setState1("中国");ori.setState2("强盛");ori.setState3("繁荣");System.out.println("===初始化状态===\n"+ori);caretaker.setMemento("001",ori.createMemento());ori.setState1("软件");ori.setState2("架构");ori.setState3("优秀");System.out.println("===修改后状态===\n"+ori);ori.restoreMemento(caretaker.getMemento("001"));System.out.println("===恢复后状态===\n"+ori);}
}

备忘录模式的优缺点和适用场景

备忘录模式的优点有

  • 当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
  • 备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。

备忘录模式的缺点

  • 在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。

如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

大话设计模式18----备忘录模式相关推荐

  1. java备忘录模式应用场景_图解Java设计模式之备忘录模式

    图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...

  2. java之备忘录模式,java设计模式之备忘录模式

    java设计模式之备忘录模式 代码无错便是优? 简介: 在不破坏封装性的前提下 , 捕获一个对象的内部状态,并在该对象之外保存这个状态 , 这样以后就可以将该对象恢复到原先保存的状态 . 备忘录模式就 ...

  3. Alamps学习设计模式之备忘录模式(笑话:劫个色OR抢个鸡蛋版)

    //设计模式之备忘录模式(月光宝盒版),只要喊菠萝菠萝蜜,就能返回事件的原点.//至尊宝//爱你一万年 class LoverWords {// 模拟Memento     private Strin ...

  4. 设计模式之备忘录模式 转载

    https://juejin.im/post/59c8eb6951882564c5164c5f 设计模式之备忘录模式 备忘录模式 介绍 是一种行为模式 用于保存对象当前状态,并在之后恢复到此状态(后悔 ...

  5. java备忘录模式 类图,Android编程设计模式之备忘录模式详解

    本文实例讲述了Android编程设计模式之备忘录模式.分享给大家供大家参考,具体如下: 一.介绍 备忘录模式是一种行为模式,该模式用于保存对象当前状态,并且在之后可以再次恢复到此状态,这有点像我们平时 ...

  6. 大话设计模式(二)代理模式

    大话设计模式(二)代理模式 前言 代理模式(Proxy Pattern)是GoF 23种Java常用设计模式之一.代理模式的定义:Provide a surrogate or placeholder ...

  7. 设计模式之备忘录模式(Memento)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  8. 大话设计模式—责任链模式

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为 ...

  9. 【设计模式】—— 备忘录模式Memento

    前言:[模式总览]----------by xingoo 模式意图 这个模式主要是想通过一个对象来记录对象的某种状态,这样有利于在其他需要的场合进行恢复. 该模式还有跟多可以扩展的地方,比如可以记录多 ...

  10. 设计模式复习-备忘录模式

    #pragma once #include "stdafx.h" #include<string> #include<iostream> using nam ...

最新文章

  1. 网络推广产品中网站的标题如何设置更利于SEO?
  2. 用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联。
  3. ip(IP)地址详解!
  4. leetcode之Divide Two Integers
  5. 关于web自动化操作的分析和基类的实现
  6. 2015年网页设计最佳颜色搭配的9种选择
  7. linux php 执行python,Linux(Ubuntu)下php使用exec调用python程序返回json数据
  8. 3行代码实现ftp 上传、下载、删除操作集合
  9. 聊聊近期的感受和10月文章精选!
  10. 2020中国男士美妆市场洞察报告
  11. 情感分析技术在美团推荐系统中的探索与应用
  12. Centos7 时间不正确修复
  13. o'Reill的SVG精髓(第二版)学习笔记——第四章
  14. css 适配mac 字体,CSS:仅在mac上使用字体
  15. java栈和队列的区别是什么意思_java中的栈和队列有什么区别
  16. 【已解决】The server cannot or will not process the request due to something that is perceived ..
  17. android 如何去控制第三方音乐播放app之控制QQ音乐
  18. Karl Guttag:AR眼镜应根据用途来设计,VST并未解决技术难题
  19. 绿联硬盘盒挂载linux,绿联sata硬盘盒,2.5/3.5寸外置usb3.0移动硬盘盒
  20. C语言基础篇02:单链表实现学生成绩管理系统

热门文章

  1. 最近很多人问我:saiku下载不下来
  2. Docker容器与本地文件相互拷贝
  3. 海云安应用安全测试、移动应用安全、开发安全再次上榜
  4. Excel 2011 显示被隐藏的第一行
  5. date format picture ends before converting entire input string
  6. 码率,帧率,分辨率_详解
  7. 各大工作室都在用的视觉特效软件,开启你的虚拟制作之旅
  8. nacos连接mysql出现:Could not create connection to database server. Attempted reconnect 3 times. Giving u
  9. html 滑屏 效果,HTML5 web app实现手动页面滑屏效果
  10. 揭秘JavaScript中“神秘”的this关键字