特点
备忘录模式通常来讲有3个类,一个需要备忘存档的Memo
类,一个发起者Initiator
,还有一个管理Meno
的类MenoManager
。备忘录模式运用也比较广泛,如:撤销、回滚、悔棋、游戏存档等场景。备忘录模式解耦了Initiator
和MomeManager
、能查看到一定时期的历史数据、能防止误操作等优点,但同时也最大的缺点会产生大量的历史数据、会比较占用空间。本文将实现一个比较容易的存档和回滚到某个时间段的功能。
类图如下:
说明 :
Memo
为一个pojo,拥有content
和time
字段;
Initiator
拥有content
字段,表示当前版本内容,可以是提交存档的,也可以是没有提交存档的,有创建一个存档对象的一个方法;
MemoManager
存档对象一个管理对象,内部持有一个集合,主要对外提供存档、查询、删除的方法;
需求说明
提供让用户能存档、查询存档、回滚到某个版本、查看当前版本的功能接口。
代码实现
Memo
package org.example.memo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 备忘录类
*/
@Data
@Accessors(chain = true)
public class Memo {
/**
* 内容
*/
private String content;
/**
* 存档时间
*/
private long time = System.currentTimeMillis();
@Override
public String toString() {
return "Memo{" +
"content='" + content + '\'' +
", time=" + time +
'}';
}
}
Initiator
@Component
public class Initiator {
// 持有备忘对象的状态(内容)
private String content;
public Memo createMemo(){
return new Memo().setContent(content);
}
public String getContent(){
return this.content;
}
public void setContent(String content){
this.content = content;
}
}
MemoManager
/**
* 管理存档对象
*/
@Component
public class MemoManager {
private final List<Memo> list = new ArrayList<>();
public MemoManager save(Memo memo){
list.add(memo);
return this;
}
public List<Memo> getList(){
return list;
}
public Memo getByTime(long time){
Optional<Memo> optional = list.stream()
.filter(memo -> memo.getTime() == time)
.findFirst();
if (optional.isPresent()){
return optional.get();
}
return null;
}
public boolean del(Memo memo){
return list.remove(memo);
}
}
MemoController
@RestController
@RequestMapping("/memo")
@Log4j2
public class MemoController {
@Autowired
private MemoManager memoManager;
@Autowired
private Initiator operator;
@GetMapping("/save")
public ResponseEntity<Boolean> save(@RequestParam String content){
operator.setContent(content);
Memo memo = operator.createMemo();
log.info("开始存档...");
memoManager.save(memo);
log.info("存档完成...");
return ResponseEntity.ok(true);
}
@GetMapping("/show")
public ResponseEntity<List<Memo>> show(){
return ResponseEntity.ok(memoManager.getList());
}
@GetMapping("/rollback")
public ResponseEntity<Memo> rollback(@RequestParam Long time){
Memo byTime = memoManager.getByTime(time);
if (byTime == null){
throw new RuntimeException("参数错误");
}
operator.setContent(byTime.getContent());
Memo memo = operator.createMemo();
memoManager.save(memo);
memoManager.del(byTime);
return ResponseEntity.ok(memo);
}
@GetMapping("/current")
public ResponseEntity<Memo> current(){
String content = operator.getContent();
if (content == null){
throw new RuntimeException("还为初始化...");
}
return ResponseEntity.ok(operator.createMemo());
}
}
测试
测试采用postman
,分别调用save
方法,区分内部内容,然后展示存档的集合,通过获取当前的对象的状态为集合中最后一次加入的内容;
存档3次的数据
[
{
"content": "测试1",
"time": 1614936504329
},
{
"content": "测试2",
"time": 1614936508458
},
{
"content": "测试3",
"time": 1614936512663
}
]
当前的内容
{
"content": "测试3",
"time": 1614936594077
}
回滚当前的内容到 time=1614936508458
的时刻,并保存,查看数据
[
{
"content": "测试1",
"time": 1614936504329
},
{
"content": "测试3",
"time": 1614936512663
},
{
"content": "测试2",
"time": 1614936785894
}
]
{
"content": "测试2",
"time": 1614936817664
}