デザインパターン メディエータパターン

2012.01.30kickbaseActionScript3.0


今回はデザインパターンのひとつ、メディエータパターンについての記事です。

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

メディエータパターン : 複雑に連携を取り合うオブジェクト(Colleague)を調停者(Mediator)に一元管理させるパターン

This movie requires Flash Player 9

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

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

  • 総勢70個の円がそれぞれボタンとしてする( もちろんロールオーバー時に指カーソルになる )
  • クリック時にインタラクション( 円が大きくなる )があり、ボタン機能がオフとなる
  • 他のボタンを押した際、以前押していた円は通常状態にリセットされる
  • 上記を踏まえた上で、数パターンの実装を行いました。

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

    This movie requires Flash Player 9

    01:総当りリセット→押された円のインタラクション
    間違いではないが、インスタンスの数だけリセット処理が実行されてしまい、効率がよくない(ほとんどのインスタンスはリセットを行う必要がないため)
    またOOPの視点からもスマートな実装とは言えない(インタラクションの実装はBallクラスに書かれているべき)

    Main

    //配列の全メンバに対してリセット処理
    for (var i: int = 0; i < _arr.length; i++) 
    {  
    	var ball:Ball = _arr[i]  as Ball;
    	ball.buttonMode = ball.mouseEnabled = true;
    	Tweener.addTween(ball, { scaleX:1, scaleY:1, time:0.4 , transition:Equations.easeOutBack} );
    }
    
    //押された円に対してのみ処理
    var current:Ball = e.target as Ball;
    current.buttonMode = current.mouseEnabled = false;
    Tweener.addTween(current, { scaleX:1.8, scaleY:1.8, time:0.3 , transition:Equations.easeOutExpo } );
    
    trace("Click!");
    

    02:半分OOP
    Ballクラスにenabledプロパティを実装したことにより、無駄なリセット処理が実行されるのを防いでいる。
    しかし、クリックの状態をMainクラスが条件分岐で管理しているため、疎結合となっていない。また条件分岐部分もスマートな実装とは言えない

    Main

    //ステージクリック時には動作を行わない
    if (e.target is Ball) 
    {
    	var num:uint = _arr.length;
    	while (num--) 
    	{
    		var ball:Ball = _arr[num]  as Ball;
    		if (e.target == ball) 
    		{
    			if (ball.enabled) { ball.currentClicked(); }
    		}
    		else 
    		{
    			if (!ball.enabled) { ball.reset(); }
    		}
    	}
    }
    

    Ball

    // 自体がクリックされた
    public function currentClicked():void 
    {
    	_enabled = false;
    	this.buttonMode = false;
    	Tweener.addTween(this, { scaleX:1.8, scaleY:1.8, time:0.3 , transition:Equations.easeOutExpo } );
    	trace("Click!");
    }
    
    // 円の状態をリセットするメソッド
    public function reset():void 
    {
    	_enabled = true;
    	this.buttonMode = true;
    	Tweener.addTween(this, { scaleX:1, scaleY:1, time:0.4 , transition:Equations.easeOutBack} );
    }
    

    03:メディエータパターン

    Main

    var col:int = 10;
    var offset:int = 50;
    for (var i: int = 0; i < 70; i++)
    {
    	var ball:Ball = new Ball();
    	ball.x = 60 * (i % col) + offset;
    	ball.y = 60 * Math.floor(i / col) + offset;
    	addChild(ball);
    	ball.mediator = _mediator;
    }
    

    Ball

    private function onClick(e:MouseEvent):void 
    {
    	_mediator.register(this); //メディエータに通知する
    	currentClicked();
    }
    

    Mediator

    package gof
    {
    	/**
    	 * ...
    	 * @author kickbase
    	 */
    	public class Mediator 
    	{
    		private var last:Ball = null; //最後に押された円(初期状態ではどれも押されてないのでnull)
    		
    		/*--------------------------------------------------------------------------
    		 * register
    		 *---------------------------------------------------------------------*//**
    		 * 円が押された時に実行されるメソッド。以下の流れで処理をする
    		 * 1.最後に押された円がnullでなければ(つまり初期状態でなければ)、その円の状態ををリセットする
    		 * 2.変数lastに、新しい円を代入する
    		 * 
    		 * @param ball     <p>Ballクラスのインスタンス。メディエーターに管理される側のインスタンス(Colleague)</p>
    		 */
    		public function register(ball:Ball):void
    		{
    			if (last != null) last.reset();
    			last = ball;
    		}
    	}
    }
    

    サンプルのダウンロード

    参考サイト

    しっぽ流デザインパターン講座(F-site講演資料)
    feb19.jp blog – AS3 で GoF デザインパターン [16] – Mediator
    Mediator パターン (前編)【閃光的網站・弛緩複合体 -Review Division-】


    ページトップへ