?**定義**:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣以后就可將
該對象恢復到原先保存的狀態。
## 一般模式:

Originator發起人角色
---|記錄當前時刻的內部狀態,負責定義那些屬于備份范圍的狀態,負責創建和恢復備忘錄數據
Memento備忘錄角色
---|負責存儲Originator發起人對象的內部狀態,在需要的時候提供發起人需要的內部狀態
Caretaker備忘錄管理員角色
---|對備忘錄進行管理、保存和提供備忘錄。
~~~
public class MementoTest {
public static void main(String[] args) {
//定義一個備忘錄的發起者
Originator origin = new Originator();
origin.setState("你好!");
//定義一個備忘錄的管理者
Caretaker care = new Caretaker();
//創建一個備忘錄
care.setMemento(origin.createMemento());
origin.setState("去死吧!");
//恢復原有的數據
origin.restoreMemento(care.getMemento());
System.out.println(origin.getState());
}
}
/**
* 備忘錄發起人的角色,
* 備忘錄中保存的就是該類的內容。
* @author admin
*
*/
class Originator{
//一個String類型表示當前狀態
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//創建一個備忘錄角色,用于時刻存儲數據。
public Memento createMemento(){
return new Memento(this.state);
}
//回復原來的數據
public void restoreMemento(Memento memento){
this.setState(memento.getState());
}
}
/**
* 備忘錄角色,
* 該類用于備份、存儲原有數據。
* @author admin
*
*/
class Memento{
//一個String類型表示當前狀態
private String state = "";
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
/**
* 備忘錄的管理類
* 對備忘錄進行管理、保存和存儲
* @author admin
*/
class Caretaker{
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
~~~
## 一個例子:
模擬月光寶盒中,至尊寶阻止白晶晶自殺的橋段。當白晶晶在洞內自殺,至尊寶沒有來得及救,于是就使用月光寶盒--菠蘿菠蘿蜜
任何就回到上一個狀態,繼續去救白晶晶,知道能夠成功救到為止。
這個例子可以說明,救白晶晶之前,首先保存一個狀態命名為1,從這一狀態出發,如果沒有成功,就回到1狀態。

~~~
public class MementoT {
public static void main(String[] args) {
//創建一個發起者,(看見白晶晶在自殺)
SaveLifeAction action = new SaveLifeAction();
action.setState("白晶晶被至尊寶傷透了心...準備拿劍抹脖子自殺");
//月關寶盒時刻記錄每一瞬間
BoxManager boxManager = new BoxManager();
boxManager.setBoxMemento(action.createMemento());
action.setState("白晶晶自殺死了...");
System.out.println(action.getState());
System.out.println("---至尊寶拿著月關寶盒,回去救她----");
//至尊寶拿著月關寶盒,回去救她
action.restoreMemento(boxManager.getBoxMemento());
//回到上一狀態
System.out.println(action.getState());
action.setSuccess(true);
if(action.isSuccess()){
System.out.println("----白晶晶成功獲救!");
}
}
}
/**
* 該類是發起者類,
* 設置負責創建和恢復備忘錄
* @author admin
*
*/
class SaveLifeAction{
//定義一個狀態,用于描述當前正在做什么..
private String state="";
//設置是否救成功
private boolean isSuccess;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
//創建一個備份的狀態
public BoxMemento createMemento(){
return new BoxMemento(this.state);
}
//恢復到原來的狀態
public void restoreMemento(BoxMemento boxMemento){
this.setState(boxMemento.getState());
}
}
/**
* 該類是備忘錄類
* 相當于故事中的月光寶盒,他帶你回到上一個狀態。
* 內部實現的原理就是,保存上一狀態而已。
* @author admin
*
*/
class BoxMemento{
private String state="";
public BoxMemento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
/**
* 備忘錄的管理者,
* 誰拿到月光寶盒,誰就可以操縱月光寶盒,
* 就可以回到過去。
* @author admin
*
*/
class BoxManager{
private BoxMemento boxMemento;
public BoxMemento getBoxMemento() {
return boxMemento;
}
public void setBoxMemento(BoxMemento boxMemento) {
this.boxMemento = boxMemento;
}
}
~~~
**備忘錄模式的使用場景**
---|需要保存和恢復數據的相關狀態場景。
---|提供一個可回滾(rollback)的操作,比如word中Ctrl+Z的組合鍵。
---|需要監控的副本場景中。
---|數據庫連接的事務管理就是用的備忘錄模式。
## 備忘錄的擴展
---|1、實現java類中的Cloneable實現備忘錄模式
???? 使用clone方式的備忘錄模式,可以使用在比較簡單的場景或者比較單一的場景中,
???? 盡量不要與其他的對象產生嚴重的耦合關系。
~~~
public class MementoExpand {
public static void main(String[] args) {
//定義一個發起人
OriginClass origin = new OriginClass();
origin.setState("我的原始狀態");
//創建備份
origin.createOrigin();
origin.setState("我的現在狀態..");
System.out.println(origin.getState());
System.out.println("------我不喜歡現在的狀態-------");
//恢復原來的狀態
origin.restoreOrigin();
System.out.println(origin.getState());
}
}
/**
* 發起者實現Cloneable接口,完成自身的備忘錄設置。
* 無需接觸其他類來保存自身的當前狀態。
* @author admin
*
*/
class OriginClass implements Cloneable{
private String state;
//自身的備忘錄角色
private OriginClass backUp;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//創建備份
public void createOrigin(){
this.backUp = (OriginClass) this.clone();
}
//恢復原來的信息
public void restoreOrigin(){
this.setState(backUp.getState());
}
@Override
protected Object clone() {
try {
return (OriginClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
~~~
---|2多狀態的備忘錄模式
~~~
/**
* 通過java.beans.Introspector類獲取其他類中的屬性和方法
* @author admin
*
*/
public class BeanUtil {
public static void main(String[] args) {
//創建一個發起者
MyOringin origin = new MyOringin("lzl",10000,"程序員");
System.out.println("在百度公司里:"+origin.toString());
//在百度公司創建備份
MyMementor mementor = origin.createMemento();
System.out.println("感覺太累了,跳槽的阿里巴巴...");
origin.setName("lzl");
origin.setPosition("程序員");
origin.setSalary(12000);
System.out.println("跳槽到阿里:"+origin.toString());
System.out.println("----------------在這里更累,跟著老大,10天沒合眼...想回到百度了.");
origin.restoreMemento(mementor);
System.out.println("回到百度,還是很輕松的。。"+origin.toString());
}
//獲取發起者類中的屬性參數,并保存在hashMap中
public static HashMap<String, Object> backUpProp(Object bean){
HashMap<String, Object> result = new HashMap<String, Object>();
//獲得Bean描述
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//返回PropertyDescriptor類型的javaBean描述
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
//遍歷返回的javaBean
for(PropertyDescriptor des : descriptors){
String fieldName = des.getName();
//讀取屬性的方法
Method getter = des.getReadMethod();
//讀取屬性值
Object fieldValue = getter.invoke(bean, new Object[]{});
if(!fieldName.equalsIgnoreCase("class")){
result.put(fieldName, fieldValue);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
//把HashMap中的值設置到bean中。
public static void restoreProp(Object bean,HashMap<String, Object> propMap){
//獲取BeanInfo
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
//獲取PropertyDescriptor的對象數組
PropertyDescriptor[] descripors = beanInfo.getPropertyDescriptors();
//增強for循環,遍歷所有的屬性,設置到bean中
for(PropertyDescriptor des : descripors){
//獲取key值對象
String fieldName = des.getName();
//如果包含這個屬性
if(propMap.containsKey(fieldName)){
//獲取屬性set的方法
Method setter = des.getWriteMethod();
setter.invoke(bean, new Object[]{propMap.get(fieldName)});
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 類的發起者,模擬擁有多個屬性。
* @author admin
*
*/
class MyOringin{
//姓名
private String name;
//薪水
private double salary;
//職位
private String position;
public MyOringin(String name,double salary,String position) {
this.name = name;
this.salary = salary;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
//創建一個備份
public MyMementor createMemento(){
//將方法屬性存儲到BeanUtil.backUpProp()中的hashMap中
return new MyMementor(BeanUtil.backUpProp(this));
}
public void restoreMemento(MyMementor memento){
BeanUtil.restoreProp(this, memento.getBeanMap());
}
@Override
public String toString() {
return "姓名:"+this.name+"\t職位:"+this.position
+"\t薪水:"+this.salary+"\t";
}
}
/**
* 備忘錄類,用于保存原有的狀態。
* @author admin
*/
class MyMementor{
//定義一個hashMap來接收發起者的所有屬性狀態備份
private HashMap<String, Object> beanMap = new HashMap<String, Object>();
public MyMementor(HashMap<String, Object> beanMap) {
this.beanMap = beanMap;
}
public HashMap<String, Object> getBeanMap() {
return this.beanMap;
}
public void setBeanMap(HashMap<String, Object> beanMap) {
this.beanMap = beanMap;
}
}
~~~
- 前言
- 6大設計原則(一)---單一職責原則
- 6大設計原則(二)---里氏替換原則
- 6大設計原則(三)---依賴倒置原則
- 6大設計模式(四)----接口隔離原則
- 6大設計原則(五)---迪米特法則
- 6大設計原則(六)---開閉原則。
- 設計模式(一)---單例模式
- 設計模式(二)---工廠方法模式
- 設計模式(三)---抽象工廠模式
- 設計模式(四)---模板方法模式
- 設計模式(五)---建造者模式
- 設計模式(六)---代理模式
- 設計模式(七)---原型模式
- 設計模式(八)---中介者模式
- 設計模式(九)---命令模式
- 設計模式(十)---責任鏈模式
- 設計模式(十一)---裝飾模式
- 設計模式(十二)---策略模式
- 設計模式(十三)---適配器模式
- 設計模式(十四)---迭代器模式
- 設計模式(十五)---組合模式
- 設計模式(十六)---觀察者模式
- 設計模式(十七)---門面模式
- 設計模式(十八)---備忘錄模式
- 設計模式(十八)---訪問者模式
- 設計模式(二十)---狀態模式
- 設計模式(二十二)---享元模式
- 設計模式(二十三)---橋梁模式