一、背景介绍
最近在做一学期的语文课,每一节课结束的时候,需要将这节课上到哪儿了给记录下来;以便于下次再上课的时候接着上,这样一个需求。
于是乎想到了设计模式的备忘录模式,并且结合自己最近研究的面向对象和面向过程边界的梳理,再探状态模式有了全新的认识;甚至可以说过目不忘,希望将这样的一个能力和思考带给每一位读者朋友
要求:所有设计上的实现都要严格符合面向对象
二、思路&方案
- 1.备忘录模式简介
- 2.备忘录模式的类图
- 3.备忘录模式中符合面向对象的地方
- 4.备忘录模式按照面向对象还可以优化的地方
- 5.备忘录模式的扩展——json转化、序列化和反序列化
三、过程
1.简介,定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
2.类图
package com.a7DesignPattern.a3BehaviorType.a07Memento; /** * 功能描述: * * @Author:makang * @Date: 2021/5/28 18:30 */ public class Originator { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public void SetMemento(Memento memento){ this.state = memento.getState(); } public Memento CreateMemento(){ return new Memento(state); } public void Show(){ System.out.println("state="+state); } }
package com.a7DesignPattern.a3BehaviorType.a07Memento; /** * 功能描述: * * @Author:makang * @Date: 2021/5/28 18:29 */ public class Memento { private String state; Memento(String state){ this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } }
package com.a7DesignPattern.a3BehaviorType.a07Memento; /** * 功能描述: * * @Author:makang * @Date: 2021/5/28 18:34 */ public class Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }
package com.a7DesignPattern.a3BehaviorType.a07Memento; /** * 功能描述: * * @Author:makang * @Date: 2021/5/28 18:37 */ public class Client { public static void main(String[] args) { Originator o = new Originator(); o.setState("on"); o.Show(); Caretaker caretaker = new Caretaker(); caretaker.setMemento(o.CreateMemento()); o.setState("off"); o.Show(); o.SetMemento(caretaker.getMemento()); o.Show(); } }
3.符合面向对象的地方
3.1.Originator 类中执行具体Memento的实例化,并且在构造函数中将状态值传进去进行保存
3.2.Originator 类中,进行对象状态恢复的时候,是将Memento对象传入到Originator对象中,进行具体状态值的恢复操作
4.按照面向对象还可以优化的地方
4.1.Memento类的构造是没必要的,可以直接在Caretaker中将Originator对象做一个深复制当做保留的带状态的对象
注:这里单独造了一个Memento对于读者理解的时候会更加的方便,因为将本来隐式的内容通过明确的类以及实例化的对象表示出来了更容易让读者理解
5.扩展-json转化、序列化
1.json转化可以对等为Caretaker类;通过将要保存的对象转化成了json的格式
2.序列化可以对等为Caretaker类;通过将要保存的对象转化成了二进制的格式
注:这两种扩展方式相较于备忘录而言,在存储传输上更加方便;下面也提供了json转化以及序列化的一个demo
package com.tfjy.util; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import java.io.*; public class damo { private static final File SAVE_FILE = new File("D:" + File.separator + "demo.Class"); public static void saveObject(Object object) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE)); oos.writeObject(object); // 序列化 oos.close(); } public static Object loadObject() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE)); Object obj = ois.readObject(); // 反序列化 ois.close(); return obj; } public static void main(String[] args) throws Exception { //将类中重写的toString方法注释之后 ,下面json转化的例子才能实现 String json = JSONObject.toJSONString(new Class(new Person("p",11),"class",12)); System.out.println(json); //将类中重写的toString方法的注解打开之后,下面序列化和反序列化的例子才能实现 saveObject(new Class(new Person("p",11),"class",12));// 序列化 Class c = (Class)loadObject(); System.out.println(c); // 反序列化 } public static class Person implements Serializable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String name, int age) { this.name = name; this.age = age; } // @Override // public String toString() { // return "Person{" + // "name='" + name + '\'' + // ", age=" + age + // '}'; // } } public static class Class implements Serializable{ private Person person; private String name; @JSONField(serialize = false) private int age; public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // @Override // public String toString() { // return "Class{" + // "person=" + person + // ", name='" + name + '\'' + // ", age=" + age + // '}'; // } public Class(Person person) { this.person = person; } public Class(Person person, String name, int age) { this.person = person; this.name = name; this.age = age; } } }
四、总结
- 1.再探备忘录模式和之前的理解完全不同,多了几个维度就将它瞬间转化成自己的知识了
- 2.通过json转化、序列化和备忘录放到一起去对比,又通透了很多
- 3.结合设计模式的类型,要解决的场景再理解起来更明确了
- 4.这次对于设计模式的总结又上了一个层次;之前备忘录模式和状态模式总混,现在对于两者的边界非常清晰
五、升华
1.通过从底层明确边界之后,向上再梳理的时候会产生一种降维打击的效果
2.设计模式就是将知识敲碎了再重组的一个过程
扩展:今天还看了一下fastjson的源码,其中的通过判断注解不进行序列化的逻辑。下面是对应的一个截图