Role
Originator:メモを作成して現在の内部状態を保存したり、メモを使用して内部状態を復元したりできる通常のクラスです。通常、内部状態を保存する必要があるクラスは、元のクラスとして設計されています。
Memento(メモ):元のデバイスの内部状態を保存し、元のデバイスに従って保存する内部状態を決定します。メモのデザインは通常、元のデバイスのデザインを参照し、実際のニーズに応じてメモクラスの属性を決定できます。メモオブジェクトは、イニシエータ自体と担当者以外のクラスでは直接使用できないことに注意してください。イニシエータの設計メカニズムは、プログラミング言語によって異なります。
担当者(担当者):管理者とも呼ばれ、メモの保存は行いますが、操作やメモの内容の確認はできません。1つ以上のメモオブジェクトは、責任のある人間に保存でき、オブジェクトの保存のみを担当し、オブジェクトを変更することはできません。オブジェクトの実装の詳細を知る必要はありません。
メモモデルの中核は、メモクラスと、メモの管理を担当する人間のデザインです。
例:チェスの例を再生すると、チェスをプレイしたり、チェスを後悔したり、後悔したチェスを取り消したりすることができます。
チェスマン、元のプレーヤーの役割
package memento.demo1;
/**
* 棋子类 Chessman,原发器角色
*/
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 void setLabel(String label) {
this.label = label;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public String getLabel() {
return label;
}
public int getX() {
return x;
}
public int getY() {
return 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();
}
public void show() {
System.out.println(String.format("棋子<%s>:当前位置为:<%d, %d>", this.getLabel(), this.getX(), this.getY()));
}
}
メモの役割 ChessmanMemento
package memento.demo1;
/**
* 备忘录角色
*/
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 String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
担当者 MementoCaretaker
package memento.demo1;
import java.util.ArrayList;
/**
* 负责人角色
*/
class MementoCaretaker {
//定义一个集合来存储备忘录
private ArrayList mementolist = new ArrayList();
public ChessmanMemento getMemento(int i) {
return (ChessmanMemento) mementolist.get(i);
}
public void addMemento(ChessmanMemento memento) {
mementolist.add(memento);
}
}
チェスクライアント、MementoCaretaker
オブジェクトを維持
package memento.demo1;
/**
* 棋子客户端,维护了一个 MementoCaretaker 对象
*/
class Client {
private static int index = -1;
private static MementoCaretaker mc = new MementoCaretaker();
public static void main(String args[]) {
Chessman chess = new Chessman("车", 1, 1);
play(chess);
chess.setY(4);
play(chess);
chess.setX(5);
play(chess);
undo(chess, index);
undo(chess, index);
redo(chess, index);
redo(chess, index);
}
//下棋,同时保存备忘录
public static void play(Chessman chess) {
mc.addMemento(chess.save());
index++;
chess.show();
}
//悔棋,撤销到上一个备忘录
public static void undo(Chessman chess, int i) {
System.out.println("******悔棋******");
index--;
chess.restore(mc.getMemento(i - 1));
chess.show();
}
//撤销悔棋,恢复到下一个备忘录
public static void redo(Chessman chess, int i) {
System.out.println("******撤销悔棋******");
index++;
chess.restore(mc.getMemento(i + 1));
chess.show();
}
}
出力は次のとおりです。チェスを後悔することに成功、後悔するチェスを無効にすることに成功
棋子<车>:当前位置为:<1, 1>
棋子<车>:当前位置为:<1, 4>
棋子<车>:当前位置为:<5, 4>
******悔棋******
棋子<车>:当前位置为:<1, 4>
******悔棋******
棋子<车>:当前位置为:<1, 1>
******撤销悔棋******
棋子<车>:当前位置为:<1, 4>
******撤销悔棋******
棋子<车>:当前位置为:<5, 4>
クラス図は以下の通りです
メモモードの概要メモモードの主な利点は次のとおりです。
状態を復元するための実装メカニズムを提供し、ユーザーが特定の履歴ステップに簡単に戻ることができるようにします。新しい状態が無効または問題がある場合、一時的に保存されたメモを使用して状態を復元できます。
メモは情報のカプセル化を実現します。メモオブジェクトは元のオブジェクトの状態を表したものであり、他のコードによって変更されることはありません。メモは発信者の状態を保存し、リストやスタックなどを使用してメモオブジェクトを保存すると、複数の取り消し操作を実現できます。
メモモードの主な欠点は次のとおりです。
リソースの消費量が多すぎます。元のクラスのメンバー変数が多すぎて保存できない場合、必然的に大量の記憶域を占有する必要があります。オブジェクトの状態が保存されるたびに、特定のシステムリソースが消費されます。
該当するシナリオ:
オブジェクトの状態のすべてまたは一部を特定の時点で保存し、後で必要になったときに以前の状態に復元して、取り消し操作を実行できるようにします。
外部オブジェクトがオブジェクトの履歴状態のカプセル化を破壊しないようにし、オブジェクトの履歴状態の実装の詳細を外部オブジェクトに公開しないようにします。