【设计模式 - 18】之备忘录模式(Memento)

1      模式简介

备忘录模式的定义:

备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象,用作“后悔药”,即取消上次操作或返回到以前的某个版本。

 

备忘录模式的应用实例:

1)        Windows系统中的Ctrl+Z;

2)        浏览器等软件中的后退按钮功能;

3)        数据库的事务管理及回滚功能;

4)        游戏存档。

 

备忘录模式的优点:

1)        给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态;

2)        实现了信息的封装,使得用户不需要关心状态的保存细节。

 

备忘录模式的缺点:

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

 

使用备忘录模式的注意事项:

在使用备忘录模式的时候,为了节约内存,一般会将原型模式和备忘录模式结合起来使用。

 

2      案例

本案例模拟数据库中的回滚功能。我们将创建一个类来管理对User用户表的操作。


具体代码如下:

备忘录管理类UserCaretaker中的代码如下:

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 备忘录管理类,其中存储所有曾经操作后的数据,单例
 */
public class UserCaretaker {
	private static UserCaretaker instance; // 单例对象

	// 存储所有用户备忘录的集合,key是回滚点名称,value是备忘录对象
	private Map<String, List<HashMap<String, String>>> mementoes;

	private UserCaretaker() {
		this.mementoes = new HashMap<>();
	}

	// 单例方法
	public static UserCaretaker getInstance() {
		if (instance == null) {
			synchronized (UserCaretaker.class) {
				if (instance == null) {
					instance = new UserCaretaker();
				}
			}
		}
		return instance;
	}

	// 添加备忘录
	public void saveMemento(String name, List<HashMap<String, String>> memento) {
		if (!mementoes.containsKey(name)) {
			mementoes.put(name, memento);
		}
	}

	// 取出某个备忘录
	public List<HashMap<String, String>> rollbackMemento(String name) {
		if (mementoes.containsKey(name)) {
			return mementoes.get(name);
		}
		return null;
	}
}
测试类Test中的代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Test {
	public static void main(String[] args) {
		// 创建备忘录集合类
		UserCaretaker caretaker = UserCaretaker.getInstance();
		// 创建用户表
		List<HashMap<String, String>> table1 = new ArrayList<>();

		// 向表中添加数据
		table1.add(makeMap("Jack", "20", "Beijing"));
		table1.add(makeMap("Rose", "16", "Shanghai"));
		table1.add(makeMap("Tom", "22", "Nanjing"));
		table1.add(makeMap("David", "10", "Qingdao"));
		// 存储为备忘录
		caretaker.saveMemento("data_added", table1);
		// 打印表中的数据
		System.out.println("--------------初始化数据表---------------");
		selectAllFromTable(table1);

		// 修改表中的数据
		List<HashMap<String, String>> table2 = copyList(table1);
		updateData(table2, "Rose", "88", "America");
		// 存储为备忘录
		caretaker.saveMemento("rose_updated", table2);
		// 打印表中的数据
		System.out.println("--------------修改表中数据---------------");
		selectAllFromTable(table2);

		// 删除表中的数据
		List<HashMap<String, String>> table3 = copyList(table2);
		deleteData(table3, "Tom");
		// 存储为备忘录
		caretaker.saveMemento("tom_deleted", table3);
		// 打印表中的数据
		System.out.println("--------------删除表中数据---------------");
		selectAllFromTable(table3);

		// 回滚到data_added节点
		List<HashMap<String, String>> t = caretaker.rollbackMemento("data_added");
		// 存储为备忘录
		caretaker.saveMemento("rollback_add", t);
		// 打印表中的数据
		System.out.println("--------------回滚到data_added节点---------------");
		selectAllFromTable(t);
	}

	// 根据提供的数据生成一条数据
	private static HashMap<String, String> makeMap(String name, String age, String address) {
		HashMap<String, String> map = new HashMap<>();
		map.put("name", name);
		map.put("age", age);
		map.put("address", address);
		return map;
	}

	// 更新一条数据
	private static void updateData(List<HashMap<String, String>> table, String name, String age, String address) {
		for (HashMap<String, String> map : table) {
			if (map.get("name").equals(name)) {
				map.put("age", age);
				map.put("address", address);
			}
		}
	}

	// 删除一条数据
	private static void deleteData(List<HashMap<String, String>> table, String name) {
		for (HashMap<String, String> map : table) {
			if (map.get("name").equals(name)) {
				table.remove(map);
			}
		}
	}

	// SELECT * FROM tb_user
	public static void selectAllFromTable(List<HashMap<String, String>> table) {
		System.out.println("name\t\tage\taddress");
		for (HashMap<String, String> user : table) {
			System.out.println(user.get("name") + "\t\t" + user.get("age") + "\t" + user.get("address"));
		}
		System.out.println();
	}

	// 复制一个List(List不能用“=”赋值,只能复制)
	public static List<HashMap<String, String>> copyList(List<HashMap<String, String>> table) {
		List<HashMap<String, String>> list = new ArrayList<>();
		for (HashMap<String, String> map : table) {
			HashMap<String, String> m = new HashMap<>();
			m.put("name", map.get("name"));
			m.put("age", map.get("age"));
			m.put("address", map.get("address"));
			list.add(m);
		}
		return list;
	}
}
运行结果如下图所示:



最后贴出备忘录模式的GitHub代码地址:【GitHub - Memento】


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值