设计模式之备忘录模式-“自述历史”模式

  1. 备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

  1. 我们刚才遇到的所有问题都是封装 “破损” 造成的。 一些对象试图超出其职责范围的工作。 由于在执行某些行为时需要获取数据, 所以它们侵入了其他对象的私有空间, 而不是让这些对象来完成实际的工作。

  1. 备忘录模式将创建状态快照 (Snapshot) 的工作委派给实际状态的拥有者原发器 (Originator) 对象。 这样其他对象就不再需要从 “外部” 复制编辑器状态了, 编辑器类拥有其状态的完全访问权, 因此可以自行生成快照。

  1. 模式建议将对象状态的副本存储在一个名为备忘录 (Memento) 的特殊对象中。 除了创建备忘录的对象外, 任何对象都不能访问备忘录的内容。 其他对象必须使用受限接口与备忘录进行交互, 它们可以获取快照的元数据 (创建时间和操作名称等), 但不能获取快照中原始对象的状态。

  1. 这种限制策略允许你将备忘录保存在通常被称为负责人 (Caretakers) 的对象中。 由于负责人仅通过受限接口与备忘录互动, 故其无法修改存储在备忘录内部的状态。 同时, 原发器拥有对备忘录所有成员的访问权限, 从而能随时恢复其以前的状态。

  1. 在文字编辑器的示例中, 我们可以创建一个独立的历史 (History) 类作为负责人。 编辑器每次执行操作前, 存储在负责人中的备忘录栈都会生长。 你甚至可以在应用的 UI 中渲染该栈, 为用户显示之前的操作历史。

  1. 当用户触发撤销操作时, 历史类将从栈中取回最近的备忘录, 并将其传递给编辑器以请求进行回滚。 由于编辑器拥有对备忘录的完全访问权限, 因此它可以使用从备忘录中获取的数值来替换自身的状态。

  1. 举例说明

以保存游戏进度为例,在游戏角色大战Boss前将该角色的状态存储,与Boss作战后角色的各项能力会下降,如果没有通关,则可利用备忘录进行恢复到战前状态。

  • 游戏角色类

package com.zyh.designpattern.memento;
public class PlayRole {
private int vitality;
private int aggressivity;
private int defencivity;
public PlayRole(int vitality, int aggressivity, int defencivity) {
super();
this.vitality = vitality;
this.aggressivity = aggressivity;
this.defencivity = defencivity;
}
public PlayRole() {}
public int getVitality() {
return vitality;
}
public void setVitality(int vitality) {
this.vitality = vitality;
}
public int getAggressivity() {
return aggressivity;
}
public void setAggressivity(int aggressivity) {
this.aggressivity = aggressivity;
}
public int getDefencivity() {
return defencivity;
}
public void setDefencivity(int defencivity) {
this.defencivity = defencivity;
}
public RoleMemento createMemento() {
RoleMemento memento = new RoleMemento();
memento.setAggressivity(aggressivity);
memento.setDefencivity(defencivity);
memento.setVitality(vitality);
return memento;
}
public void setMemento(RoleMemento memento) {
this.aggressivity = memento.getAggressivity();
this.defencivity = memento.getDefencivity();
this.vitality = memento.getVitality();
}
public void showState() {
System.out.println("攻击力:" + this.aggressivity + "|防御力:" + this.defencivity
+ "|生命力:" + this.vitality);
}
}
  • 备忘录类

package com.zyh.designpattern.memento;
public class RoleMemento {
private int vitality;
private int aggressivity;
private int defencivity;
public int getVitality() {
return vitality;
}
public void setVitality(int vitality) {
this.vitality = vitality;
}
public int getAggressivity() {
return aggressivity;
}
public void setAggressivity(int aggressivity) {
this.aggressivity = aggressivity;
}
public int getDefencivity() {
return defencivity;
}
public void setDefencivity(int defencivity) {
this.defencivity = defencivity;
}
}
  • 管理者类

package com.zyh.designpattern.memento;
public class Caretaker {
RoleMemento memento;
public RoleMemento getMemento() {
return memento;
}
public void setMemento(RoleMemento memento) {
this.memento = memento;
}
}
  • 客户端

package com.zyh.designpattern.memento;
public class Client {
public static void main(String[] args) {
// 测试程序
// 新建角色
PlayRole role = new PlayRole(100, 100, 100);
// 新建管理者
Caretaker taker = new Caretaker();
// 角色初始状态
System.out.println("游戏刚开始,角色各属性:");
role.showState();
// 利用备忘录模式保存当前状态
System.out.println("\n【保存游戏状态!】\n");
taker.setMemento(role.createMemento());
role.setAggressivity(20);
role.setDefencivity(30);
role.setVitality(0);
// 大战过后,角色能力值下降
System.out.println("与Boss对战后,角色各项能力已大大下降:");
role.showState();
// 恢复保存的角色状态
role.setMemento(taker.getMemento());
System.out.println("\n【恢复保存的角色状态!】");
System.out.println("\n恢复后角色的当前状态:");
role.showState();
}
}
  • C++代码

#include <iostream>
#include <string>
using namespace std;
//备忘者类备份发起者的状态
class Memento
{
public:
 //构造的时候备份数据
 Memento(string state):_state(state){};
 string _state;
};
//发起者类备份自己的状态
class Originator
{
public:
 //建立备份
 Memento* createBackups(){
 return new Memento(_state);
 }
 //恢复备份内容
 void restoreBackups(Memento* memento){
 _state = memento->_state;
 }
 //显示状态
 void show() {
 cout<<_state<<endl;
 }
 string _state;
};
//管理者类管理备份
class Caretaker
{
public:
 //得到备份
 Memento* getMemento(){
 return _memento;
 }
 //设置备份
 void setMemento(Memento* memento){
 _memento = memento;
 }
 Memento *_memento;
};
//客户端代码
#include "Memento.h"
int main(void)
{
 //设置和显示状态
 Originator o;
 o._state = "ON";
 o.show();
 //创建备份
 Memento* m = o.createBackups();
 //管理备份
 Caretaker c;
 c.setMemento(m);
 //设置和显示状态
 o._state = "OFF";
 o.show();
 //恢复备份
 m = c.getMemento();
 o.restoreBackups(m);
 //显示状态
 o.show();
 getchar();
 return 0;
}
  1. “自述历史”模式

  在“自述历史”模式里面,发起人角色自己兼任负责人角色。发起人角色同时还兼任负责人角色,也就是说它自己负责保持自己的备忘录对象。

public class Originator {

    public String state;

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

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

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

    private class Memento implements MementoIF {
        private String state;

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

        public String getState() {
            return state;
        }
    }
}
  • 客户端角色类

@Slf4j
public class Client {

    public static void main(String[] args) {
        Originator originator = new Originator();
        originator.changeState("state 0");
        MementoIF memento = originator.createMemento();
        originator.changeState("state 1");
        originator.restoreMemento(memento);
        log.info("{}", originator.state);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chuxuezhe_987

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值