上文(设计模式-中介者模式):https://blog.csdn.net/qq_16498553/article/details/106591438
目录
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
背景
美国大片好多超级英雄的角色,一个人从头干到尾,还毫发无损,真的是大家很崇拜的对象,而超级英雄平常也是普通人状态,等到世界末日或者说变身的时候才变成超级牛逼的一种状态,干完架又恢复成普通人,这里其实跟备忘录模式有点像,普通状态和超级英雄状态。
备忘录模式是什么?
备忘录模式(Memento Pattern),属于行为模式,定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便恢复到原先保存的状态。
角色
Originator(发起人角色):负责创建、记录、恢复自身内部状态或数据。
Mement(备忘录角色):负责存储Originator的内部状态或数据,并且可以提供Originator的内部状态或数据。
Caretaker(备忘录管理员角色):负责管理备忘录,只负责将备忘录内容进行传递;
备忘录模式可以干嘛?
备忘录将当前的对象,通过一个存储容器,将该对象或对象的一些内部状态信息,存储一份,然后通过该备份,当原对象需要恢复的时候通过备忘录管理员角色,对原有的备忘录数据进行恢复。该模式主要用于恢复和保存对象的状态或对象。
优点:
遵循迪米特法则:由于角色的备份信息由备忘录管理员角色,只负责管理,而不能直接去修改备忘录的信息,并且该备忘录最终操作也由发起人来决定是否恢复。
恢复机制:提供了一套,当用户需要的时候将内部状态或信息保存、恢复,并且用户不需要关心具体细节。
缺点:
开销大:由于一个备份就需要在内存中存放一个对象,如果是多对象和多状态的场景,可能内存开销就很大了。
个人理解:
备忘录就像我们平常手机里面的通讯录,为了防止丢失记录一份,需要的时候直接调出来就拨打了,也可以这么理解为电影里面的超级英雄角色,关键的时候变身超级英雄等到干完活后,恢复成普通人。
备忘录模式类图
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
实现代码
/**
* @Auther: csh
* @Date: 2020/6/10 14:39
* @Description:人 (Originator)
*/
public class Person {
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public void changeStatus(){
this.status="变身超人";
}
//保存状态
public Memento saveStateToMemento(){
return new Memento(status);
}
//通过记录获取状态
public void getStatusFromMemento(Memento memento){
if(null!=memento){
this.status = memento.getState();
}else{
System.out.println("没有状态恢复!");
}
}
}
/**
* @Auther: csh
* @Date: 2020/6/10 14:41
* @Description:Mement(备忘录角色)
*/
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
/**
* @Auther: csh
* @Date: 2020/6/10 14:46
* @Description:Caretaker(备忘录管理员角色)
*/
public class CareTaker {
//存储备份的列表
private List<Memento> mementoList = new ArrayList <Memento>();
//添加
public void add(Memento memento) {
if(null!=memento){
this.mementoList.add(memento);
}
}
//获取方式
public Memento getToMemento(Memento memento){
for (Memento mo : mementoList) {
if(mo.getState().equals(memento.getState())){
return mo;
}
}
return null;
}
//获取
public Memento get(int index){
return mementoList.get(index);
}
//删除
public boolean del(Memento memento){
if(null!=memento){
return this.mementoList.remove(memento);
}
return false;
}
}
/**
* @Auther: csh
* @Date: 2020/6/10 14:51
* @Description:
*/
public class Client {
public static void main(String[] args) {
CareTaker careTaker = new CareTaker();
Person person = new Person();
person.setStatus("普通人");
System.out.println("------保存状态--------");
Memento memento = person.saveStateToMemento();
careTaker.add(memento);
System.out.println("变身前状态:"+person.getStatus());
System.out.println("--------变身--------");
person.changeStatus();
System.out.println("拯救世界去了:"+person.getStatus());
System.out.println("继续恢复平凡人的身份......");
person.getStatusFromMemento(careTaker.get(0));
System.out.println("恢复后:"+person.getStatus());
}
}
结果
------保存状态--------
变身前状态:普通人
--------变身--------
拯救世界去了:变身超人
继续恢复平凡人的身份......
恢复后:普通人
更多案例请下载源码参考,这里就不一一贴出。
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
备忘录模式在实际日常开发过程中,还是比较常见,有时候还有多状态多备份的需求,甚至有时候会根据时间来保存,这时候的话就可能通过数据库或者一些缓存池来记录,当需要恢复到某个状态或某个时间节点的时候,对其指定恢复。当然如果完全放到缓存中对系统性能有一定影响,特别是那种备份次数特别多的时候,可能会导致内存开销非常高,而GC又回收不到然后就各种超时异常出现,一查发现内存GG了....建议如果是备忘录需要结合业务或者给个过期时间,通过记录后,规定的时候失效,可以放到晚上或者说隔多长时间,要不然可真的可能一直保存该种信息就...
场景
Windows 里的 ctri + z。
IE 中的后退操作
数据库的事务管理