デザインパターン コマンドパターン

2012.01.30kickbaseActionScript3.0


今回はデザインパターンのひとつ、コマンドパターンについての記事です。

2012.1.28に開催された第8回 Morioka.asで発表させていただいた資料となります。テーマは「ミニマリズム」というもの。
様々な捉え方ができるテーマでしたが、無駄を削ぎ落したロジックということで、デザインパターンを用いた実装としました。

コマンドパターン : 処理をオブジェクトとしてカプセル化し、アンドゥ/リドゥ、ロギング、キューイングなど、様々な操作を可能にするパターン
※今回の例では簡略化のため、最小限の機能として直列/並列実行のみを実装しています

This movie requires Flash Player 9

※SWF領域を一回クリックすることでスライドを操作できます。クリックで次へ、キーボードの左右で前と次へ移動できます

実装する内容としては、下記の通り

  • 円がX軸上を移動し、ステージの中心に
  • 画面に50個配置された四角形がステージ中心に移動
  • 円がY軸上を移動しながら拡大
  • 上記を踏まえた上で、数パターンの実装を行いました。

    以下は各実装のポイントを抜粋したものです。
    ※サンプルには全クラスが含まれています

    01:Tweenerのdelayプロパティを調整する
    各モーションのプロパティが密に結合してしまっているので、修正が非常に困難な実装と言えます。
    Flashコンテンツではモーションを試行錯誤する事がとても重要なので、メンテナンス性が低い実装は避けましょう。

    Main

    Tweener.addTween(_ball, { x:stage.stageWidth / 2, time:0.4, transition:Equations.easeInSine } );
    			for (var i: int = 0; i < _arr.length; i++) 
    			{  
    				var square:Square = _arr[i]  as Square;
    				Tweener.addTween(square, { x:stage.stageWidth / 2, y:stage.stageHeight / 2, alpha:0, delay:0.4 + 0.02 * i, time:0.8, transition:Equations.easeOutBounce } );
    			}
    			Tweener.addTween(_ball, { y:stage.stageHeight / 2, scaleX:10, scaleY:10,  delay:0.4 + 0.02 * i + 0.8, time:1.0, transition:Equations.easeInOutExpo } );
    

    02:コマンドパターン
    実装する上で最も重要な点は下記のふたつ

  • 全てのコマンドにexecuteメソッドを実装し、リクエスト( 実際に行う処理 )はexecuteを通して実行するようにする
  • リクエスト終了時にEvent.COMPLETEイベントを送出する
  • 全てのコマンドは「execute()すれば目的の処理が実行される」ことが保証されているので、いつでも交換可能です。
    またリクエスト終了時に内部的にEvent.COMPLETEイベントが送出されるので、これを追いかけることによって直列/並列実行を可能にしています。

    Main

    var parallel:ParallelCommand = new ParallelCommand();
    			for (var i: int = 0; i < _arr.length; i++) 
    			{  
    				var square:Square = _arr[i]  as Square;
    				parallel.addCommand(new TweenerCommand(square, { x:stage.stageWidth / 2, y:stage.stageHeight / 2, alpha:0, delay:0.02 * i, time:0.8, transition:Equations.easeOutBounce } ));
    			}
    			
    			var serial:SerialCommand = new SerialCommand();
    			serial.addCommand(new TweenerCommand(_ball, { x:stage.stageWidth / 2, time:0.4, transition:Equations.easeInSine } ));			
    			serial.addCommand(parallel);			
    			serial.addCommand(new TweenerCommand(_ball, { y:stage.stageHeight / 2, scaleX:10, scaleY:10,  delay:0, time:1.0, transition:Equations.easeInOutExpo } ));
    			serial.addCommand(new TraceCommand("All commands are end."))
    			
    			serial.execute();
    

    Command:全てのコマンドの基底クラス

    package gof.command 
    {
    	import flash.events.Event;
    	import flash.events.EventDispatcher;
    	/**
    	 * ...
    	 * @author kickbase
    	 */
    	public class Command implements ICommand 
    	{
    		//内部にイベントディスパッチャーを保持しておく
    		protected var _eventDispatcher:EventDispatcher;
    		
    		public function Command() 
    		{
    			_eventDispatcher = new EventDispatcher();
    		}
    		
    		/* INTERFACE gof.command.ICommand */
    		
    		public function execute():void 
    		{
    			//コマンド実行後に完了イベント送信メソッドを実行
    			dispatchCompleteEvent();
    		}
    		
    		public function addEventListener(type:String, listener:Function):void 
    		{
    			_eventDispatcher.addEventListener(type, listener);
    		}
    		
    		public function removeEventListener(type:String, listener:Function):void 
    		{
    			_eventDispatcher.removeEventListener(type, listener);
    		}
    		
    		//コマンド終了時にEvent.COMPLETEイベントを送出
    		protected function dispatchCompleteEvent():void
    		{
    			_eventDispatcher.dispatchEvent( new Event(Event.COMPLETE) );
    		}
    	}
    }
    

    03:Tween24
    おまけとして国産高機能トゥイーンライブラリ、Tween24を使用した例を紹介します。メソッドチェーンを利用した高速なコーディングが可能です。
    標準でシリアル/パラレルリストをサポートしています。スペシャルプロパティも直接トゥイーン可能と非常に多機能。実行速度もTweenerより高速となっています。
    僕自身、慣れ親しんでいるという理由で開発終了して久しいTweenerを使い続けていたのですが、数あるTweenライブラリの中でやっと出会えた大本命です。

    Main

    Tween24.serial(
    				Tween24.tween(_ball, 0.4, Tween24.ease.SineIn).x(stage.stageWidth / 2),
    				Tween24.lag(
    					0.02,
    					Tween24.tween(_arr, 0.8, Tween24.ease.BounceOut).xy(stage.stageWidth / 2, stage.stageHeight / 2).fadeOut()
    				),
    				Tween24.tween(_ball, 1, Tween24.ease.ExpoInOut).y(stage.stageHeight / 2).scale(10)
    			).play();
    

    サンプルのダウンロード

    参考サイト

    しっぽ流デザインパターン講座(F-site講演資料)
    feb19.jp blog – AS3 で GoF デザインパターン [22] – Command
    fladdict » AS3で非同期処理を行う為のcommandsライブラリ
    [AS3] Commandライブラリを作って非同期処理をする 1 « きんくまデザイン


    ページトップへ