ActionScript 3 (Flash/AIR): GoF デザインパターン – Memento

状態を保存するデザインパターン。カプセル化の原則を破る事無くインスタンスの状態を保存するという感じです。

状態を残しておきたいプロパティなどをひとまとめにした Memento オブジェクトを Caretaker の配列に保存しておき、戻すときは状態を戻すクラス内部で Memento を展開するといった感じ。

アプリケーションのアンドゥ処理とかに使われたりするそうです。その場合 Command パターンとかも考慮するといいようです。

ActionScript: Memento.as

package jp.feb19.gof.memento
{
	public class Memento
	{
		private var _mState:String;
		
		public function Memento(stateSetter:String)
		{
			_mState = stateSetter;
		}
		
		public function getState():String
		{
			return _mState;
		}
	}
}

ActionScript: Caretaker.as

package jp.feb19.gof.memento
{
	public class Caretaker
	{
		private var _storage:Array;
		
		public function Caretaker()
		{
			_storage = [];
		}
		
		public function addMemento(memento:Memento):void
		{
			_storage.push(memento);
		}
		
		public function getMemento(index:int):Memento
		{
			return _storage[index];
		}
	}
}

ActionScript: Originator.as

package jp.feb19.gof.memento
{
	public class Originator
	{
		private var _mState:String;
		
		public function Originator()
		{
		}
		
		public function setState(mState:String):void
		{
			trace("状態を設定: " + mState);
			_mState = mState;
		}
		
		public function createMemento():Memento
		{
			trace("現在の状態のメメントを作成");
			return new Memento(_mState);
		}
		
		public function setMemento(memento:Memento):void
		{
			_mState = memento.getState();
			trace("メメント取得後のオリジネイターの状態: " + _mState);
		}
	}
}

テストクラス

ActionScript: MementoTest.as

package jp.feb19.gof.memento
{
	import flash.display.Sprite;
	
	public class MementoTest extends Sprite
	{
		public function MementoTest()
		{
			super();
			
			var caretaker:Caretaker = new Caretaker();
			var originator:Originator = new Originator();
			
			originator.setState("1st");
			originator.setState("2nd");
			caretaker.addMemento(originator.createMemento());
			originator.setState("3rd");
			caretaker.addMemento(originator.createMemento());
			originator.setState("4th");
			
			// 一番最初に保存した状態に戻す
			originator.setMemento(caretaker.getMemento(0));
		}
	}
}

出力

状態を設定: 1st
状態を設定: 2nd
現在の状態のメメントを作成
状態を設定: 3rd
現在の状態のメメントを作成
状態を設定: 4th
メメント取得後のオリジネイターの状態: 2nd

あまりにもメモリを食うインスタンスを Memento で保持し続けてるとメモリが足りなくなっちゃうので Caretaker のストレージを最大何個までとかしておいたりすることもあるようです。