天天看點

設計模式(十八)---備忘錄模式一般模式:  一個例子:備忘錄的擴充

 定義:在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可将

  該對象恢複到原先儲存的狀态。

一般模式:

設計模式(十八)---備忘錄模式一般模式:  一個例子:備忘錄的擴充

  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;
	}
}
           

繼續閱讀