ステータスを一括で管理するクラス EventDispatcher機能付
AS3の仕事が増える中、AS2で使っていたBroadcasterクラスというオリジナルクラスのようなものがほしくなり、AS3用に作りました。
まず断っておきますが、これは汎用的に使えるクラスではなくノウハウのようなものです。でも一部は汎用的に使えるコードですのでカスタマイズして使ってみると何かと重宝します。
ステータスを一括で管理するというケースではイベント処理とデータの保持の両方が必要になります。
例えば「本」のようなアプリケーションの場合、「いま何ページを表示している」といったデータはそのアプリケーションの中では一つなはずですね。でもそのデータを知りたい、もしくは変更したいオブジェクトはアプリケーションのなかで点在するものです。これをうまく解決するのにはオブザーバーパターンを使えばいいわけですが、それ自体はEventDispatcherクラスを使えば簡単に実現できます。
一方アプリケーションが中くらいの規模になってくると(例えばフルスクリーンのちょっとリッチなサイト)イベントごとにクラスを作っているとクラスだらけになってしまいます。またステータスが変わったらそれをみんなに知らせたいというケースが大半なはずですね。(ちなみにここでいうステータスとはステータスパターンとはなんの関係もありません。)
つまりオブザーバーパターンの実装とステータスの保持はセットだと話が早いというわけです。また、ステータスの種類はいくらでも増やせたほうがいいですね。
サンプルです。
package{import flash.events.Event;/*** ...* @author DYO*/public class MovieStatus extends Event{//▼カスタマイズ ココカラ/*--------------------------------------------------* page--------------------------------------------------*/static public const PAGE:String = "movieStatusPage";static private var _page:int;static public function get page():int { return _page; }static public function set page(value:int):void {if(_page != value){var _value = _page;_page = value;myDispatcher.dispatchEvent(new MovieStatus({type:PAGE,current:_page,pre:_value}));}}//▲カスタマイズ ココマデstatic private var myDispatcher:MyDispatcher;public var status:Object;public function MovieStatus(_type:Object, bubbles:Boolean = false, cancelable:Boolean = false) {var type = _type is String ? _type : _type.type;super(type, bubbles, cancelable);status = _type is String ? {current:null,pre:null,type:type} : _type;}public override function clone():Event {return new MovieStatus(type);}static public function init() {if(!myDispatcher)myDispatcher = new MyDispatcher();}static public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {myDispatcher.addEventListener(type, listener, useCapture, priority,useWeakReference);}static public function dispatchEvent(evt:Event):Boolean {return myDispatcher.dispatchEvent(evt);}static public function hasEventListener(type:String):Boolean {return myDispatcher.hasEventListener(type);}static public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {myDispatcher.removeEventListener(type, listener, useCapture);}static public function willTrigger(type:String):Boolean {return myDispatcher.willTrigger(type);}}}import flash.events.Event;import flash.events.EventDispatcher;import flash.events.IEventDispatcher;class MyDispatcher implements IEventDispatcher {private var dispatcher:EventDispatcher;public function MyDispatcher() {dispatcher = new EventDispatcher(this);}public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {dispatcher.addEventListener(type, listener, useCapture, priority);}public function dispatchEvent(evt:Event):Boolean {return dispatcher.dispatchEvent(evt);}public function hasEventListener(type:String):Boolean {return dispatcher.hasEventListener(type);}public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {dispatcher.removeEventListener(type, listener, useCapture);}public function willTrigger(type:String):Boolean {return dispatcher.willTrigger(type);}}- Download this code: MovieStatus.as
使うほうは
まずMovieStatusをinit()します。(これはアプリケーション内で一回でよし。ドキュメントクラスのコンストラクタでやるとベター)
つぎにファンクション定義。function onPageChanged(e:MovieStatus){trace(e.status.current);}
最後にイベント登録。MovieStatus.addEventListener(MovieStatus.PAGE,onPageChanged);
あとはMovieStatus.page = 1;とかすると先ほどのonPageChangedが呼ばれます。
今回はpageというステータスを用意しましたが、サンプルの「カスタマイズ」の部分を増やしたり改造したりすることで、アプリケーションごとに設定することができます。
本当は最初にinitするという仕様が腑に落ちないのですが、staticなクラスにしたかったことと、一つのクラスにまとめたかったことと、singletonなんかつかっていちいちインスタンス化するのが面倒だったことがあってこうなりました。ベターな方法があれば教えてください。
最近のコメント