デザインパターン テンプレートメソッドパターン

2011.03.07kickbaseActionScript3.0


今回はデザインパターンのひとつ、テンプレートメソッドパターンについての記事です。2011.3.5に開催された東京ひよこの会(第1回勉強会)で発表させていただいた資料となります。テーマは「Flashのボタンについて語り合おう!」というもの。
複数のボタンを扱う際「ロールオーバー、ロールアウト、マウスダウン/アップ時の演出は共通で、自身の画像設定方法とクリック時の処理を変更したい」といった場合が多いと思います。そこでテンプレートメソッドパターンを使用してボタン群を制御してみました。

テンプレートメソッドパターン : 複数のオブジェクトに同じ処理を定義しかつ、ある処理に対しては個別の機能を持たせたいときに便利なパターン

This movie requires Flash Player 9

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

コードの説明は上記スライドを参照してください。以下にポイントとなるTemplateクラス、Button1~3クラスのソースを掲載しておきます。
※サンプルには全クラスが含まれています

Template

package button 
{
	import caurina.transitions.Tweener;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author kickbase
	 */
	public class Template extends Sprite
	{
		public function Template() 
		{
			if (Object(this).constructor == Template) throw new Error("Templateは抽象クラスなので、インスタンス化禁止です。サブクラスを作成してください。");
			templateMethod();
		}
		
		//テンプレートなのでfinal属性とします
		final private function templateMethod():void
		{
			setImage();
			this.buttonMode = true;
			this.addEventListener(MouseEvent.ROLL_OVER, onOver);
			this.addEventListener(MouseEvent.ROLL_OUT, onOut);
			this.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
			this.addEventListener(MouseEvent.MOUSE_UP, onUp);
			this.addEventListener(MouseEvent.CLICK, onClick);
		}
		
		private function onOver(e:MouseEvent):void 
		{
			Tweener.addTween(this, { _brightness:0.4, time:0.2 } );
		}
		
		private function onOut(e:MouseEvent):void 
		{
			Tweener.addTween(this, { _brightness:0, time:0.8 } );
		}
		
		private function onDown(e:MouseEvent):void 
		{
			Tweener.addTween(this, { _brightness: -0.1, time:0.1 } );
		}
		
		private function onUp(e:MouseEvent):void 
		{
			Tweener.addTween(this, { _brightness:0.4, time:0.1 } );
		}
		
		//クリック時の処理です。サブクラス側で書き換えます
		protected function onClick(e:MouseEvent):void 
		{
			throw new Error("onClickは抽象メソッドです。サブクラスでオーバーライドしてください。");
		}
		
		//ボタンの画像設定です。サブクラス側で書き換えます
		protected function setImage():void
		{
			throw new Error("setImageは抽象メソッドです。サブクラスでオーバーライドしてください。");
		}
	}
}

Button1

package button 
{
	import flash.events.MouseEvent;
	import flash.net.navigateToURL;
	import flash.net.URLRequest;
	
	/**
	 * ...
	 * @author kickbase
	 */
	public class Button1 extends Template
	{
		[Embed(source = '../assets/btn1.png')]
		private var BG:Class;
		
		/*--------------------------------------------------------------------------
		 * setImage
		 *---------------------------------------------------------------------*//**
		 * <p>Embedした画像を表示リストに追加します</p>
		 */
		override protected function setImage():void 
		{
			addChild(new BG());
		}
		
		/*--------------------------------------------------------------------------
		 * onClick
		 *---------------------------------------------------------------------*//**
		 * <p>ブランクで外部サイトへ</p>
		 */
		override protected function onClick(e:MouseEvent):void 
		{
			navigateToURL(new URLRequest("http://www.yahoo.co.jp/"), "_blank");
		}
	}
}

Button2

package button 
{
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author kickbase
	 */
	public class Button2 extends Template
	{
		/*--------------------------------------------------------------------------
		 * setImage
		 *---------------------------------------------------------------------*//**
		 * <p>SWC(MovieClipを継承)からインスタンス化したものを表示リストに追加します</p>
		 */
		override protected function setImage():void 
		{
			addChild(new Button2UI());
		}
		
		/*--------------------------------------------------------------------------
		 * onClick
		 *---------------------------------------------------------------------*//**
		 * <p>トレースします</p>
		 */
		override protected function onClick(e:MouseEvent):void 
		{
			trace(this + "を押しました");
		}
	}
}

Button3

package button 
{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.net.URLRequest;
	/**
	 * ...
	 * @author kickbase
	 */
	public class Button3 extends Template
	{
		static public const ON_CLICK:String = "onClick";
		
		/*--------------------------------------------------------------------------
		 * setImage
		 *---------------------------------------------------------------------*//**
		 * <p>外部画像をロードして表示リストに追加します</p>
		 */
		override protected function setImage():void 
		{
			var loader:Loader = new Loader();
			loader.load(new URLRequest("import/btn3.jpg"));
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
		}
		
		private function onIOError(e:IOErrorEvent):void 
		{
			trace( "e.text : " + e.text );
		}
		
		private function onComplete(e:Event):void 
		{
			var loader:Loader = LoaderInfo(e.target).loader;
			addChild(loader);
			loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
		}
		
		/*--------------------------------------------------------------------------
		 * onClick
		 *---------------------------------------------------------------------*//**
		 * <p>イベントを送信します</p>
		 */
		override protected function onClick(e:MouseEvent):void 
		{
			dispatchEvent(new Event(ON_CLICK));
		}
	}
}

サンプルのダウンロード


ページトップへ