设计模式之备忘录模式(上)

备忘录模式
1)概述
1.定义

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,可以在以后将对象恢复到原先保存的状态。

2.作用

备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。

3.结构图
4.角色

Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。

Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。

Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查,在管理者类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。

5.代码实现

原发器类Originator

public class Originator {
    private String state;
    public Originator(){}
    
  // 创建一个备忘录对象
    public Memento createMemento() {
    return new Memento(this);
    }
 
  // 根据备忘录对象恢复原发器状态
    public void restoreMemento(Memento m) {
     state = m.state;
    }
 
    public void setState(String state) {
        this.state=state;
    }
 
    public String getState() {
        return this.state;
    }
}

备忘录类Memento

//备忘录类,默认可见性,包内可见
class Memento {
    private String state;
 
    public Memento(Originator o) {
    state = o.getState();
    }
 
    public void setState(String state) {
        this.state=state;
    }
 
    public String getState() {
        return this.state;
    }
}
6.Java语言实现备忘录模式

一般将Memento类与Originator类定义在同一个包(package)中实现封装,在Java语言中可使用默认访问标识符来定义Memento类,保证只有Originator类可以对Memento进行访问。

在Memento中保存了Originator的state值,如果Originator中的state值改变之后需撤销,可以通过调用它的restoreMemento()方法进行恢复。

对于负责人类Caretaker,它用于保存备忘录对象,并提供getMemento()方法向客户端返回一个备忘录对象,原发器通过使用这个备忘录对象可以回到某个历史状态,典型的负责人类的实现代码如下:

public class Caretaker {
	private Memento memento;
 
	public Memento getMemento() {
		return memento;
	}
 
	public void setMemento(Memento memento) {
		this.memento=memento;
	}
}

在Caretaker类中不应该直接调用Memento中的状态改变方法,它的作用仅仅用于存储备忘录对象。

7.注意

设计备忘录类时需要考虑其封装性,除了Originator类,不允许其他类来调用备忘录类Memento的构造函数与相关方法,如果不考虑封装性,允许其他类调用setState()等方法,将导致在备忘录中保存的历史状态发生改变,通过撤销操作所恢复的状态就不再是真实的历史状态,备忘录模式也就失去了本身的意义。

2)完整解决方案
1.结构图

Chessman充当原发器,ChessmanMemento充当备忘录,MementoCaretaker充当负责人,在MementoCaretaker中定义了一个ChessmanMemento类型的对象,用于存储备忘录。

2.代码实现
//象棋棋子类:原发器
@Data
public class Chessman {
	private String label;
	private int x;
	private int y;
 
	public Chessman(String label,int x,int y) {
		this.label = label;
		this.x = x;
		this.y = y;
	}
	
  //保存状态
	public ChessmanMemento save() {
		return new ChessmanMemento(this.label,this.x,this.y);
	}
	
  //恢复状态
	public void restore(ChessmanMemento memento) {
		this.label = memento.getLabel();
		this.x = memento.getX();
		this.y = memento.getY();
	}
}
 
//象棋棋子备忘录类:备忘录
@Data
class ChessmanMemento {
	private String label;
	private int x;
	private int y;
 
	public ChessmanMemento(String label,int x,int y) {
		this.label = label;
		this.x = x;
		this.y = y;
	}	
}
 
//象棋棋子备忘录管理类:负责人
public class MementoCaretaker {
	private ChessmanMemento memento;
 
	public ChessmanMemento getMemento() {
		return memento;
	}
 
	public void setMemento(ChessmanMemento memento) {
		this.memento = memento;
	}
}

客户端类

public class Client {
	public static void main(String[] args) {
		MementoCaretaker mc = new MementoCaretaker();
		
		Chessman chess = new Chessman("车",1,1);
		display(chess);
		mc.setMemento(chess.save()); //保存状态		
		
		chess.setY(4);
		display(chess);
		mc.setMemento(chess.save()); //保存状态
		display(chess);
		
		chess.setX(5);
		display(chess);
		
		System.out.println("******悔棋******");	
		//恢复状态
		chess.restore(mc.getMemento()); 
		display(chess);
	}
	
	public static void display(Chessman chess) {
		System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "列。");
	}
}
相关推荐
lxyzcm18 小时前
深入理解C++23的Deducing this特性(上):基础概念与语法详解
开发语言·c++·spring boot·设计模式·c++23
越甲八千18 小时前
重温设计模式--单例模式
单例模式·设计模式
Vincent(朱志强)18 小时前
设计模式详解(十二):单例模式——Singleton
android·单例模式·设计模式
诸葛悠闲20 小时前
设计模式——桥接模式
设计模式·桥接模式
捕鲸叉1 天前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式
小小小妮子~1 天前
框架专题:设计模式
设计模式·框架
先睡1 天前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
Damon_X1 天前
桥接模式(Bridge Pattern)
设计模式·桥接模式
越甲八千2 天前
重温设计模式--享元模式
设计模式·享元模式
码农爱java2 天前
设计模式--抽象工厂模式【创建型模式】
java·设计模式·面试·抽象工厂模式·原理·23种设计模式·java 设计模式