参考:https://blog.csdn.net/weixin_48052161/article/details/119546968
备忘录模式 分类:
备忘录角色要保持完整的封装。最好的情况便是:备忘录角色只应该暴露操作内部存储属性的的接口给“备忘发起角色”。而对于其他角色则是不可见的
备忘录模式又可以分为“白箱”备忘录模式和“黑箱”备忘录模式。
“白箱”备忘录模式
备忘录角色提供一个宽接口的话,备忘录的内部存储状态就对所有对象公开,这就是“白箱实现”。
“白箱”实现破坏了封装性,但是通过程序员自律,可以方便地实现备忘录模式。
“黑箱”备忘录模式
采用内部类来控制访问权限。将备忘录角色作为“备忘发起角色”的一个私有内部类。
代码演示:
建立一个类来保存最新文章信息:
白箱:
备忘保存镜像类:
package com.example.dtest.design23.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleMemento {
private String title;
private String content;
private Date createTime;
}
真实文本类:
package com.example.dtest.design23.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleText {
private String title;
private String content;
private Date createTime;
public ArticleMemento saveToMemento(){
ArticleMemento articleMemento = new ArticleMemento(this.title, this.content, this.createTime);
return articleMemento;
}
public void getArticleFromMemento(ArticleMemento articleMemento){
this.title = articleMemento.getTitle();
this.content = articleMemento.getContent();
this.createTime = articleMemento.getCreateTime();
}
@Override
public String toString() {
return "ArticleText{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
", createTime=" + createTime +
'}';
}
}
备忘录管理者角色门面类: ArticleCaretaker
package com.example.dtest.design23.memento;
import java.util.ArrayList;
import java.util.List;
public class ArticleCaretaker {
private final List<ArticleMemento> list = new ArrayList<>();
public ArticleMemento getArticle(int index){
return list.get(index);
}
public void setArticle(ArticleMemento articleMemento){
list.add(articleMemento);
}
}
测试类:
package com.example.dtest.design23.memento;
import java.util.Date;
public class MementoTest {
public static void main(String[] args) {
// 1、新创建一个文本
ArticleText articleText = new ArticleText("标题1","内容1",new Date());
System.out.println("新建时: "+articleText.toString());
// 保存文本,备忘录
ArticleMemento articleMemento = articleText.saveToMemento();
// 创建备忘录管理值
ArticleCaretaker articleCaretaker = new ArticleCaretaker();
articleCaretaker.setArticle(articleMemento);
// 修改文本
articleText = new ArticleText("标题2","内容2",new Date());
System.out.println("修改后: "+articleText.toString());
// 3、回退到记录之前的版本
articleText.getArticleFromMemento(articleCaretaker.getArticle(0));
System.out.println("还原后: "+articleText.toString());
}
}
黑箱:
将Memento设成ArticleText02类的内部类;
将Memento的方法全部设成私有方法,这样只有它自己和发起人ArticleText02可以调用;
在外部提供一个标识接口MementoIF给Caretaker以及其他对象,标识接口MementoIF没有提供任何方法,因此对外部来说Memento对象的内容都是不可见的。
备忘接口类(对外访问):
package com.example.dtest.design23.memento.blackMemneto;
public interface MementoIF {
}
真实文本类:里面有内部类ArticleMemento2 备忘实现了MementoIF
package com.example.dtest.design23.memento.blackMemneto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleText02 {
private String title;
private String content;
private Date createTime;
// 保存一个备忘录管管理者角色的对象
private ArticleCaretaker02 caretaker02 = new ArticleCaretaker02();
public ArticleText02(String title, String content, Date createTime) {
this.title = title;
this.content = content;
this.createTime = createTime;
}
public int saveToMemento(){
int stateIndex = caretaker02.setArticle(new ArticleMemento2(this.title,this.content,this.createTime));
return stateIndex;
}
public void getArticleFromMemento(int index){
ArticleMemento2 articleMemento2 = (ArticleMemento2)caretaker02.getArticle(index);
this.title = articleMemento2.getTitle();
this.content = articleMemento2.getContent();
this.createTime = articleMemento2.getCreateTime();
}
public void modefyState(String title,String content,Date createTime){
this.title = title;
this.content = content;
this.createTime = createTime;
}
@Override
public String toString() {
return "ArticleText{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
", createTime=" + createTime +
'}';
}
@Data
@NoArgsConstructor
@AllArgsConstructor
private class ArticleMemento2 implements MementoIF{
private String title;
private String content;
private Date createTime;
}
}
备忘录管理者角色门面类: ArticleCaretaker02
package com.example.dtest.design23.memento.blackMemneto;
import java.util.ArrayList;
import java.util.List;
public class ArticleCaretaker02 {
int stateIndex = -1;
private final List<MementoIF> list = new ArrayList<>();
public MementoIF getArticle(int index){
return list.get(index);
}
public int setArticle(MementoIF articleMenento){
list.add(articleMenento);
return ++stateIndex;
}
}
测试类:
package com.example.dtest.design23.memento.blackMemneto;
import java.util.Date;
public class BlackMementoTest {
public static void main(String[] args) {
// 1、新创建一个文本
ArticleText02 articleText02 = new ArticleText02("标题1","内容1",new Date());
System.out.println("新建时: "+articleText02.toString());
// 保存文本,备忘录
int state = articleText02.saveToMemento();
// 修改文本
articleText02.modefyState("标题888", "内容888", new Date());
System.out.println("修改后; "+articleText02.toString());
// 回退到记录之前的版本
articleText02.getArticleFromMemento(state);
System.out.println("还原后:"+articleText02.toString());
}
}