七、备忘录模式Memento(行为型模式)
其目的是,在不违反封装原则的前提下.採集和备份一个对象的内部状态以便这个对象能够在以后恢复到之前的某个状态.
备忘录模式的操作过程
1、client为发起人角色创建一个备忘录对象。
2、调用发起人对象的某个操作。这个操作是能够撤销的。
3、检查发起人对象所出状态的有效性。检查的方式能够是发起人对象的内部自查。也能够由某个外部对象进行检查。
4、假设须要的话。将发起人的操作撤销。也就是说依据备忘录对象的记录。将发起人对象的状态恢复过来。
“假如”协议模式的操作过程:
1、将发起人对象做一个拷贝。
2、在拷贝上运行某个操作。
3、检查这个拷贝的状态是否有效和自恰。
4、假设检查结果是无效或者不自恰的,那么扔掉这个拷贝,并触发异常处理程序。相反。假设检查是有效和自恰的,那么在原对象上运行这个操作
显然这一做法对于撤销一个操作并恢复操作前状态较为复杂和困难的发起人对象来说是一个较为慎重和有效的做法。
“假如”协议模式的长处和缺点
详细来说,这个做法的好处是能够保证发起人对象永远不会处于无效或不自恰的状态上。这样作的短处是成功的操作必须运行两次。
假设操作的成功率较低的话。这样做就比較划算。反之就不太划算。
使用备忘录模式的长处和缺点
一、备忘录模式的长处
1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,可是必须要由发起人对象自己读取,这时,
使用备忘录模式能够把复杂的发起人内部信息对其它的对象屏蔽起来。从而能够恰当地保持封装的边界。
2、本模式简化了发起人类。发起人不再须要管理和保存其内部状态的一个个版本号,client能够自行管理他们所需
要的这些状态的版本号。
3、当发起人角色的状态改变的时候,有可能这个状态无效。这时候就能够使用临时存储起来的备忘录将状态复原。
二、备忘录模式的缺点:
1、假设发起人角色的状态须要完整地存储到备忘录对象中。那么在资源消耗上面备忘录对象会非常昂贵。
2、当负责人角色将一个备忘录 存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法
提醒用户一个操作是否非常昂贵。882——P
3、当发起人角色的状态改变的时候,有可能这个协议无效。
假设状态改变的成功率不高的话,不如採取“假如”协议模式。
public class Client {
private static Originator originator = new Originator();
private static Caretaker c = new Caretaker();
public static void main(String[] args) {
// 该发起人对象的状态
originator.setState("On");
// 创建备忘录对象,并将发起人对象的状态存储起来
c.saveMemento(originator.createMemento());
// 改动发起人对象的状态
originator.setState("Off");
// 恢复发起人对象的状态
originator.restoreMemento(c.retrieveMemento());
}
}
// 发起人角色
class Originator {
private String state;
// 工厂方法,返还一个新的备忘录对象
public Memento createMemento() {
return new Memento(state);
}
// 将发起人恢复到备忘录对象所记载的状态
public void restoreMemento(Memento memento) {
this.state = memento.getState();
}
// 状态的取值方法
public String getState() {
return this.state;
}
// 状态的赋值方法
public void setState(String state) {
this.state = state;
System.out.println("Current state = " + this.state);
}
}
/*
* 备忘录模式要求备忘录对象提供两个不同的接口:一个宽接口提供给发起人对象,还有一个窄接口提供给全部其它的对象,包含负责人对象。
* 宽接口同意发起人读取到全部的数据。窄接口仅仅同意它把备忘录对象传给其它的对象而看不到内部的数据。
*/
// 备忘录角色
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
}
/*
* 负责人角色负责保存备忘录对象,可是从不改动(甚至不查看)备忘录对象的内容(一个更好的实现是负责人对象根本无法从备忘录 对象中读取个改动其内容)
*/
// 负责人角色
class Caretaker {
private Memento memento;
// 备忘录的取值方法
public Memento retrieveMemento() {
return this.memento;
}
// 备忘录的赋值方法
public void saveMemento(Memento memento) {
this.memento = memento;
}
}
首先将发起人对象的状态设置成“On”(或者不论什么有效状态),而且创建一个备忘录对象将这个状态存储起来。然后将发起人对象的状态改成“Off”(或者不论什么状态);最后又将发起人对象恢复到备忘录对象所存储起来的状态,即“On”状态(或者先前所存储的不论什么状态)
备忘录系统运行的时序是这种:
(1)将发起人对象的状态设置成“On”。
(2)调用发起人角色的createMemento()方法,创建一个备忘录对象将这个状态存储起来。
(3)将备忘录对象存储到负责人对象中去。
备忘录系统恢复的时序是这种:
(1)将发起人对象的状态设置成“Off”;
(2)将备忘录对象从负责人对象中取出;
(3)将发起人对象恢复到备忘录对象所存储起来的状态。“On”状态。
白箱实现的优缺点
白箱实现的一个明显的好处是比較简单,因此经常常使用做教学目的。
白箱实现的一个明显的缺点是破坏对发起人状态的封装。
(2)窄接口或者黑箱实现:
//client
public class Client {
private static Originator originator = new Originator();
private static Caretaker c = new Caretaker();
public static void main(String[] args) {
// 该发起人对象的状态
originator.setState("On");
// 创建备忘录对象。并将发起人对象的状态存储起来
c.saveMemento(originator.createMemento());
// 改动发起人对象的状态
originator.setState("Off");
// 恢复发起人对象的状态
originator.restoreMemento(c.retrieveMemento());
}
}
// 发起人角色
class Originator {
private String state;
public Originator() {
}
// 工厂方法,返还一个新的备忘录对象
public MementoIF createMemento() {
return new Memento(this.state);
}
// 将发起人恢复到备忘录对象记录的状态
public void restoreMemento(MementoIF memento) {
Memento aMemento = (Memento) memento;
this.setState(aMemento.getState());
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
System.out.println("state =" + state);
}
protected class Memento implements MementoIF {
private String savedState;
public Memento(String someState) {
this.savedState = someState;
}
private void setState(String someState) {
savedState = someState;
}
private String getState() {
return savedState;
}
}
}
interface MementoIF {
}
// 备忘录角色
class Memento implements MementoIF {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
}
class Caretaker {
private MementoIF memento;
public MementoIF retrieveMemento() {
return this.memento;
}
public void saveMemento(MementoIF memento) {
this.memento = memento;
}
}
黑箱实现运行时的时序为;
(1)将发起人对象的状态设置成“On”。
(2)调用发起人角色的 createMemento()方法。创建一个备忘录对象将这个状态存储起来。
(3)将备忘录对象存储到负责人对象中去。因为负责人对象拿到的仅是 MementoIF类型,因此无法读出备忘录内部的状态。
恢复时的时序为:
(1)将发起人对象的状态设置成“Off”。
(2)将备忘录对象从负责人对象中取出。
注意此时仅能得到 MementoIF接口,因此无法读出此对象的内部状态
(3)将发起人对象的状态恢复成备忘录对象所存储起来的状态。,因为发起人对象的内部类Memento实现了MementoIF接口
这个内部类是传入的备忘录对象的真实类型,因此发起人对象能够利用内部类Memento 的私有 接口读出此对象的内部状态。
(3)存储多个状态的备忘录模式:
//发起人角色
import java.util.Vector;
import java.util.Enumeration; public class Originator{
private Vector states;
private int index; public Originator(){
states = new Vector();
index = 0;
} public Memento createMementor(){
return new Mementor(states,index);
} public void restoreMementor(Mementor memento){
states = memento.getStates();
index = memento.getIndex()。
} public void setState(String state){
this.states.addElement(state);
index ++;
} //辅助方法。打印出全部的状态
public void printStates(){
System.out.println("Total number of states: " + index);
for(Enumeration e = states.elements();e.hasMoreElements();){
system.out.println(e.nextElement());
}
}
}
//备忘录角色
import java.util.Vector; public class Memento{
private Vector states;
private int index;
//<span style="font-size: 14px; font-family: Arial, Helvetica, sans-serif;">备忘录的构造子克隆了传入的states,然后将克隆存入到备忘录对象内部,这是一个重要的细节,因为不这种话,将会</span><pre title="备忘录(Memento Pattern)模式 【行为模式第一篇】" style="font-size: 14px;"> //将会造成client和备忘录对象持有对同一个Vector对象的引用,也能够同一时候改动这个Vector对象,会造成系统崩溃。
public Memento(Vector states,int index){this.states = (Vector)states.clone();this.index = index;}//状态取值方法Vector getStates(){return states;}//检查点取值方法int getIndex(){return this.index;}}
//负责人角色
import java.util.Vector; public class Caretaker{
private Originator o;
private Vector mementos = new Vector();
private int current; public Caretaker(Originator o){
this.o = o;
current = 0;
} public int createMemento(){
Memento memento = o.createMemento();
mementos.addElement(memento);
return current ++;
} //将发起人恢复到某个检查点
public void restoreMemento(int index){
Memento memento = (Memento)mementos.elementAt(index);
o.restoreMemento(memento);
} //某个检查点删除
public void removeMemento(int index){
mementos.removeElementAt(index);
}
}
//client
public class Client{
private static Originator o = new Originator();
private static Caretaker c = new Caretaker(o);
public static void main(String[] args){
//改变状态
o.setState("state 0");
//建立一个检查点
c.createMemento();
//改变状态
o.setState("state 1"); c.createMemento(); o.setState("state 2"); c.createMemento(); o.setState("state 3"); c.createMemento(); o.setState("state 4"); c.createMemento(); o.printStates(); //恢复到第二个检查点
System.out.println("Restoring to 2"); c.restoreMemento(2); o.printStates(); System.out.println("Restoring to 0"); c.restoreMemento(0); o.printStates(); System.out.println("Restoring to 3"); c.restoreMemento(3); o.printStates(); }
}
(4)自述历史模式(备忘录模式的一个变种)
因为“自述历史”作为一个备忘录模式的特殊实现形式非常easy易懂。它可能是备忘录模式最为流行的实现形式。
//窄接口
public interface MementoIF{}
//发起人角色
public class Originator{
public String state; public Originator(){} public void changeState(String state){
this.state = state;
System.out.println("State has been changed to : " + state);
} public Memento createMemento(){
return new Memento(this);
} public void restoreMemento(MementoIF memento){
Memento m = (Memento)memento;
changeState(m.state);
} class Memento implements MementoIF{
private String state; private String getState(){
return state;
} private Memento(Originator o){
this.state = o.state;
}
}
}
//client
public class Client{
private static Originator o;
private static MementoIF memento; public static void main(String args[]){
o = new Originator();
o.changeState("State 1");
memento = o.createMemento();
o.changeState("State 2");
o.restoreMemento(memento);
}
}
七、备忘录模式Memento(行为型模式)的更多相关文章
- 设计模式20:Memento 备忘录模式(行为型模式)
Memento 备忘录模式(行为型模式) 对象状态的回溯 对象状态的变化无端,如何回溯.恢复对象在某个点的状态? 动机(Motivation) 在软件构建过程中,某些对象的状态在转换过程中,可能由于某 ...
- 设计模式15:Interpreter 解释器模式(行为型模式)
Interpreter 解释器模式(行为型模式) 动机(Motivation) 在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变 ...
- 设计模式17:Iterator 迭代器模式(行为型模式)
Iterator 迭代器模式(行为型模式) 动机(Motivation) 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码可以透 ...
- 设计模式16:Mediator 中介者模式(行为型模式)
Mediator 中介者模式(行为型模式) 依赖关系的转化 动机(Motivation) 在软件构建过程中,经常出现多个对象互相关联交互的情况,对象之间经常会维持一种复杂的应用关系,如果遇到一些需求的 ...
- 设计模式23:Visitor 访问者模式(行为型模式)
Visitor 访问者模式(行为型模式) 动机(Motivation)在软件构造过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的修改,将会给子类带来繁重的 ...
- 设计模式22:Strategy 策略模式(行为型模式)
Strategy 策略模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂:而且有时候支持 ...
- 设计模式21:State 状态模式(行为型模式)
State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...
- 设计模式19:Chain Of Responsibility 职责链模式(行为型模式)
Chain Of Responsibility 职责链模式(行为型模式) 请求的发送者与接受者 某些对象请求的接受者可能有多种多样,变化无常…… 动机(Motivation) 在软件构建过程中,一个请 ...
- 设计模式14:Command 命令模式(行为型模式)
Command 命令模式(行为型模式) 耦合与变化 耦合是软件不能抵御变化的根本性原因.不仅实体对象与实体对象之间存在耦合关系,实体对象与行为操作之间也存在耦合关系. 动机(Motivation) 在 ...
- 设计模式13:Template Method 模板方法模式(行为型模式)
Template Method 模板方法模式(行为型模式) 变与不变 变化——是软件永恒的主题,如何管理变化带来的复杂性?设计模式的艺术性和复杂度就在于如何分析,并发现体系中的变化点和稳定点,并使用特 ...
随机推荐
- Python学习日记之忽略删除字符串空白
使用Python自带的函数strip可以剔除字符串开头.结尾.两端的空白 使用场景:用户输入验证 strip : 去除字符串两端的空白 rstrip : 去除字符串末尾(右端)的空白 lstrip : ...
- 【PostgreSQL-9.6.3】物化视图
PostgreSQL 9.3 以后出现了物化视图.物化视图是由实实在在的数据组成,这是和一般视图的根本区别. 1. 物化视图创建语法如下: --创建语法 CREATE MATERIALIZED VIE ...
- 04JavaScript程序语句
JavaScript程序语句 2.6程序控制流程 2.6.1选择结构 if <逻辑表达式> 语句 else 语句 if <逻辑表达式> { 语句组 } else { 语句组} ...
- 视频剪辑生成gif格式(php外挂python程序)完美!
接到朋友的需求,朋友是做php的,让我帮忙处理php生成gif的需求.他的项目类似抖音短视频那种,就是展示出来的界面是gif动图,然后点进去是完整的视频. 我想了想,我倒是没做过php生成gif的需求 ...
- docker 1-->docker swarm 转载
实践中会发现,生产环境中使用单个 Docker 节点是远远不够的,搭建 Docker 集群势在必行.然而,面对 Kubernetes, Mesos 以及 Swarm 等众多容器集群系统,我们该如何选择 ...
- 洛谷——P4296 [AHOI2007]密码箱
P4296 [AHOI2007]密码箱 密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1. 求这个密码,$1<=n<=2,000,000,000$ 暴力枚举,数据有点儿水$O( ...
- HDU - 2044 - 一只小蜜蜂...(dp)
题意: 如题 思路: 仔细观察图 1-4和3-6其实是一样的答案,那么所有的方案都可以相减,意思为全部转化为从1开始 剩下的就是观察规律,仔细观察5号,能到5号蜂房的只有3和4,3和4到5号蜂房只有一 ...
- 后台工具screen
之前在putty之类的远程命令行操作服务器的时候,遇到关闭软件,对应的操作就会关闭.很多时候,就是开着电脑,然后挂在那里,虽然不用电脑跑,但是也耗电...主要是putty这些软件有时候会伴随黑屏崩掉. ...
- list tuple dict (列表,元祖,字典间的相互转换)
#-*- coding:UTF-8 -*- #author:RXS002 #1.字典 dict = {'name':'Zara','age':7,'class':'First'} #字典转换为字符串, ...
- Leetcode 90.子集
子集 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [1,2,2], ...