其他分享
首页 > 其他分享> > 23种设计模式之备忘录模式

23种设计模式之备忘录模式

作者:互联网

23种设计模式之备忘录模式

文章目录

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

记录一个对象的内部状态,并在该对象之外保存这个状态,当需要时能将该对象恢复到原先保存的状态。

特点

通用类图

在这里插入图片描述

备忘录模式的重要角色:

优点

缺点

应用场景

二、实现分类

标准备忘录模式

需求:

模拟用户打字功能,用户按入撤销键可以回到之前的状态,用户按入反撤销键可以回到撤销前的状态,使用备忘录模式实现该功能。

发起人:

package memento.standard;

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

public class Originator {


	//  内部状态
	private List<String> state = new ArrayList<>();

	public List<String> getState() {
		return state;
	}

	public void setState(List<String> state) {
		this.state = state;
	}

	//  创建一个备忘录
	public Memento createMemento() {
		return new Memento(state);
	}

	//  恢复一个备忘录
	public void restoreMemento(Memento memento) {
		this.setState(memento.getState());
	}


	//  ============ 自身业务逻辑=============

	//  添加一行内容
	public void add(String line) {
		state.add(line);
	}

	//  显示所有的内容
	public void display() {
		for (String s : state) {
			System.out.println(s);
		}
	}

}

备忘录:

package memento.standard;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Memento implements Serializable {
	//  发起人角色的内部状态
	private List<String> State = new ArrayList<>();

	//  构造函数传递参数
	public Memento(List<String> State) {
		this.State = State;
	}

	public List<String> getState() {
		return State;
	}

	public void setState(List<String> state) {
		this.State = state;
	}


	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	//  通过实现Serializable,对状态进行深克隆
	protected Object deepClone() throws Exception {
		//  将对象写入流中
		ByteArrayOutputStream bao = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bao);
		oos.writeObject(this);

		//  将对象从流中取出
		ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
		ObjectInputStream ois = new ObjectInputStream(bis);
		return (ois.readObject());
	}


}

管理者:

package memento.standard;

import java.util.Stack;

public class CareTaker {
	//  存储 撤销的备忘录对象
	private Stack<Memento> memento = new Stack<>();
	//  存储 反撤销的备忘录对象
	private Stack<Memento> mementoReverse = new Stack<>();

	//  添加备忘录对象
	public void setMemento(Memento memento) throws Exception {
		this.memento.push((Memento) memento.deepClone());
	}

	//  获取当前撤销备忘录对象,并保存到反撤销备忘录里(即进行Ctrl+Z操作)
	public Memento getMemento() {
		//  此处的边界处理仅作模式演示,与实际处理不符
		if (memento.size() < 0) {
			return null;
		}
		if (memento.size() == 1) {
			return mementoReverse.push(memento.pop());
		}
		mementoReverse.push(memento.pop());
		return mementoReverse.push(memento.pop());
	}

	//  获取当前反撤销备忘录对象,并保存到撤销备忘录里 (即进行Ctrl+Shift+Z操作)
	public Memento getMementoReverse() {
		//  此处的边界处理仅作模式演示,与实际处理不符
		if (mementoReverse.size() < 0) {
			return null;
		}
		if (mementoReverse.size() == 1) {
			return memento.push(mementoReverse.pop());
		}
		memento.push(mementoReverse.pop());
		return memento.push(mementoReverse.pop());
	}
}

Client:

package memento.standard;

public class Client {
	public static void main(String[] args) throws Exception {

		//  定义管理员
		CareTaker careTaker = new CareTaker();

		//  定义发起人
		Originator originator = new Originator();

		//  发起人添加内容
		originator.add("Hello World!");
		//  发起人创建一个备忘录
		careTaker.setMemento(originator.createMemento());

		//  发起人添加新的内容
		originator.add("I am in love with you!");
		//  发起人创建一个备忘录
		careTaker.setMemento(originator.createMemento());

		//  发起人添加新的内容
		originator.add("bye!");
		//  发起人创建一个备忘录
		careTaker.setMemento(originator.createMemento());

		//  打印当前内容
		System.out.println("初始状态");
		originator.display();
		System.out.println("===============");

		//  执行撤销功能
		System.out.println("撤销状态");
		//  执行第一次撤销
		System.out.println("执行第一次撤销");
		originator.restoreMemento(careTaker.getMemento());
		originator.display();
		System.out.println("===============");
		//  执行第二次撤销
		System.out.println("执行第二次撤销");
		originator.restoreMemento(careTaker.getMemento());
		originator.display();
		System.out.println("===============");

		//  执行反撤销功能
		System.out.println("反撤销状态");
		System.out.println("执行第一次反撤销");
		originator.restoreMemento(careTaker.getMementoReverse());
		originator.display();
		System.out.println("===============");
		System.out.println("执行第二次反撤销");
		originator.restoreMemento(careTaker.getMementoReverse());
		originator.display();
		System.out.println("===============");


		/**
		 * 输出结果:
		 * 初始状态
		 * Hello World!
		 * I am in love with you!
		 * bye!
		 * ===============
		 * 撤销状态
		 * 执行第一次撤销
		 * Hello World!
		 * I am in love with you!
		 * ===============
		 * 执行第二次撤销
		 * Hello World!
		 * ===============
		 * 反撤销状态
		 * 执行第一次反撤销
		 * Hello World!
		 * I am in love with you!
		 * ===============
		 * 执行第二次反撤销
		 * Hello World!
		 * I am in love with you!
		 * bye!
		 * ===============
		 */

	}
}

多状态多备份的备忘录模式

需求:

有一个bean对象有多个状态,且可以多次备份该bean对象。

工具类:

package memento.more;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;


public class BeanUtils {
   //  把bean的所有属性及数值放入到Hashmap中

   public static HashMap<String, Object> backupProp(Object bean) {
      HashMap<String, Object> result = new HashMap<>();

      try {
         //  获得bean描述
         BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
         //  获得属性描述
         PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
         //  遍历所有属性
         for (PropertyDescriptor descriptor : descriptors) {
            //  属性名称
            String fieldName = descriptor.getName();
            //  读取属性的方法
            Method readMethod = descriptor.getReadMethod();
            //  读取属性值
            Object fieldValue = readMethod.invoke(bean, new Object[]{});
            if (!fieldName.equalsIgnoreCase("class")) {
               result.put(fieldName, fieldValue);
            }
         }

      } catch (Exception e) {

      }

      return result;
   }

   public static void restoreProp(Object bean, HashMap<String, Object> propMap) {
      try {
         //  获得bean描述
         BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
         //  获得属性描述
         PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
         //  遍历所有属性
         for (PropertyDescriptor descriptor : descriptors) {
            //  属性名称
            String fieldName = descriptor.getName();
            //  如果存在该属性
            if (propMap.containsKey(fieldName)) {
               //  写属性的方法
               Method writeMethod = descriptor.getWriteMethod();
               writeMethod.invoke(bean, new Object[]{propMap.get(fieldName)});
            }
         }

      } catch (Exception e) {

      }

   }

}

Originator:

package memento.more;

public class Originator {

   //  内部状态
   private String state1 = "";
   private String state2 = "";
   private String state3 = "";

   public String getState1() {
      return state1;
   }

   public void setState1(String state1) {
      this.state1 = state1;
   }

   public String getState2() {
      return state2;
   }

   public void setState2(String state2) {
      this.state2 = state2;
   }

   public String getState3() {
      return state3;
   }

   public void setState3(String state3) {
      this.state3 = state3;
   }

   //  创建一个备忘录
   public Memento createMemento() {
      return new Memento(BeanUtils.backupProp(this));
   }

   //  恢复一个备忘录
   public void restoreMemento(Memento memento) {
      BeanUtils.restoreProp(this, memento.getStateMap());
   }

   @Override
   public String toString() {
      return "state1=" + state1 + "\nstate2=" + state2 + "\nstate3=" + state3;
   }

}

Memento:

package memento.more;

import java.util.HashMap;

public class Memento {
   //  使用HashMap存储状态
   private HashMap<String, Object> stateMap;

   public Memento(HashMap<String, Object> map) {
      this.stateMap = map;
   }

   public HashMap<String, Object> getStateMap() {
      return this.stateMap;
   }

   public void setStateMap(HashMap<String, Object> stateMap) {
      this.stateMap = stateMap;
   }
}

CareTaker:

package memento.more;

import java.util.HashMap;

public class CareTaker {
   //  容纳备忘录的容器
   private HashMap<String, Memento> container = new HashMap<>();

   public Memento getMemento(String idx) {
      return this.container.get(idx);
   }

   public void setMemento(String idx, Memento memento) {
      this.container.put(idx, memento);
   }
}

Client:

package memento.more;

public class Client {
	public static void main(String[] args) {
		//  定义出发起人
		Originator originator = new Originator();

		//  定义管理员
		CareTaker caretaker = new CareTaker();

		//初始化
		originator.setState1("Huawei");
		originator.setState2("Xiaomi");
		originator.setState3("honor");
		System.out.println("==========初始状态==========");
		System.out.println(originator);

		//  创建备忘录
		caretaker.setMemento("001", originator.createMemento());

		//  修改状态值
		originator.setState1("Apple");
		originator.setState2("Samsung");
		originator.setState3("Nokia");
		System.out.println("==========修改后的状态==========");
		System.out.println(originator);

		//  创建备忘录
		caretaker.setMemento("002", originator.createMemento());

		//  恢复第一个个指定标记的备忘录
		originator.restoreMemento(caretaker.getMemento("001"));
		System.out.println("==========恢复第一个指定标记的的状态==========");
		System.out.println(originator);

		//  恢复第二个指定标记的备忘录
		originator.restoreMemento(caretaker.getMemento("002"));
		System.out.println("==========恢复第二个指定标记的状态==========");
		System.out.println(originator);

		/**
		 * ==========初始状态==========
		 * state1=Huawei
		 * state2=Xiaomi
		 * state3=honor
		 * ==========修改后的状态==========
		 * state1=Apple
		 * state2=Samsung
		 * state3=Nokia
		 * ==========恢复第一个指定标记的的状态==========
		 * state1=Huawei
		 * state2=Xiaomi
		 * state3=honor
		 * ==========恢复第二个指定标记的状态==========
		 * state1=Apple
		 * state2=Samsung
		 * state3=Nokia
		 */
	}
}

三、总结

通俗地说,备忘录模式就是一个对象的备份模式,提供了一种程序数据的备份方法。

标签:originator,23,备忘录,println,设计模式,public,memento,out
来源: https://blog.csdn.net/space_qi/article/details/116357517