再び信号

Rober Pennerの努力のおかげで、C#からActionScriptに移行したシグナルに関するAiden Tailorの記事。 これは単なる翻訳ではなく、チートシート-記事の絞り込みです。 水がなければ、それ以上のことはありません。そのため、最も怠ziな人でも目を通り抜けることができます。 パフォーマンステストも実行されています。 この投稿は、AS3の第一人者だけでなく、コードの品質の改善に関心のあるすべての人を対象としています。Observerデザインパターンの実装の1つに関する説明が含まれているためです。 そして、 ここにビデオチュートリアルがあります。



コアは、Signalはサブスクライバーの配列を持つ独立したイベントマネージャーです。 主なアイデアは、EventDispatcherで使用される文字列比較から離れて、一連のEventを生成することです。 ここで GITリポジトリからas3ライブラリのソースを取得できます



シグナル -メインシグナル。



package insideria.basicSignal { import org.osflash.signals.Signal; public class AlarmClock { public var alarm:Signal; public function AlarmClock() { alarm = new Signal(); //   } public function ring():void { alarm.dispatch(); //   () } } } package insideria.basicSignal { import flash.display.Sprite; public class WakeUp extends Sprite { private var alarmClock:AlarmClock; public function WakeUp() { alarmClock = new AlarmClock(); alarmClock.alarm.add(onRing); //   alarmClock.ring(); } private function onRing():void { //  trace("Wake up!"); } } }
      
      







パラメーターは、シグナルコンストラクターで型をリストすることによって渡されます。



  package insideria.basicSignalArguments { import org.osflash.signals.Signal; public class AlarmClock { public var alarm:Signal; public function AlarmClock() { alarm = new Signal(String); //     } public function ring():void { alarm.dispatch("9 AM"); //  } } } package insideria.basicSignalArguments { import flash.display.Sprite; public class WakeUp extends Sprite { private var alarmClock:AlarmClock; public function WakeUp() { alarmClock = new AlarmClock(); alarmClock.alarm.add(onRing); alarmClock.ring(); } private function onRing(time:String):void { //   - ,      trace("Wake up! It's already " + time); } } }
      
      







ガベージコレクターは、サブスクライブを解除するとインスタンスを使い果たします(個人的にチェック):



  alarmClock.alarm.remove(onRing); //  alarmClock.alarm.addOnce(onRing); //   , , ,  Event.ADDED_TO_STAGE alarmClock.alarm.removeAll(); //   
      
      







DeluxeSignal-豪華な(高度な)信号により、信号の所有者と信号自体にアクセスできます。

GenericEvent (一般イベント)とカスタムパラメーター(基本信号)の両方をリスナーに送信できます。 それを使用すると、耐えられない贅沢になる場合があります(投稿の最後にあるパフォーマンステストを参照)



  package insideria.deluxeSignal { import org.osflash.signals.DeluxeSignal; import org.osflash.signals.events.GenericEvent; public class AlarmClock { public var alarm:DeluxeSignal; public var message:String; public function AlarmClock() { alarm = new DeluxeSignal(this); //   target  message = "This is a message from our AlarmClock"; } public function ring():void { alarm.dispatch(new GenericEvent()); //  GenericEvent } } } package insideria.deluxeSignal { import org.osflash.signals.events.GenericEvent; import flash.display.Sprite; public class WakeUp extends Sprite { private var alarmClock:AlarmClock; public function WakeUp() { alarmClock = new AlarmClock(); alarmClock.alarm.add(onRing); alarmClock.ring(); } private function onRing(event:GenericEvent):void { trace(event.target); // target,      trace(event.signal); //  trace(event.target.message); } } }
      
      







NativeSignal-ネイティブ信号。 ネイティブActionScriptイベントを信号に変換します。

例:

  package insideria.nativeSignals { import org.osflash.signals.natives.NativeSignal; import flash.display.Sprite; import flash.events.Event; public class AddToStage extends Sprite { public function AddToStage() { var added:NativeSignal = new NativeSignal(this, Event.ADDED_TO_STAGE, Event); //      Event' added.addOnce(onAdded); } private function onAdded(event:Event):void { graphics.beginFill(0xCCCCCC); graphics.drawRect(0, 0, 100, 100); graphics.endFill(); } } }
      
      







性能:



-プロファイルは、EventDispatcherと比較して、Signalがインスタンスごとに追加で4 kbのRAMを消費することを示しました

-シグナルはEventDispatcherより2倍遅くなりません

-Deluxe SignalはEventDispatcherの約4.5倍の速度です(この名前の理由は明らかです)

-NativeSignal-テストされていませんが、コード分析により、パフォーマンスはSignalのパフォーマンスとほぼ同じであることが示されました



実行速度テストが実行されたコード:



  public class Main extends Sprite { private static const COUNT:int = 10000; private var _signal: SignalItem; private var _dispatcher: DispatcherItem; private var t:int; private var i:int; private var test:int; public function Main() { _signal = new SignalItem(); _signal.signal.add(onSignal); test = 0; t = getTimer(); for (i = 0; i<COUNT; i++) { _signal.dispatch(); } t = getTimer()-t; trace("Main.Main(); signal : " + t); _dispatcher = new DispatcherItem(); _dispatcher.addEventListener(Event.CHANGE, onChange); test = 0; t = getTimer(); for (i = 0; i<COUNT; i++) { _dispatcher.dispatch(); } t = getTimer() - t; trace("Main.Main(); dispatcher : " + t); } private function onSignal(z:int): void { test++; } private function onChange(e:Event): void { test++; } } public class SignalItem { private var _signal:DeluxeSignal; public function SignalItem() { _signal = new DeluxeSignal(this); } public function get signal(): Signal { return _signal; } public function dispatch():void { _signal.dispatch(new GenericEvent()); } } public class DispatcherItem extends EventDispatcher{ public function DispatcherItem() { } public function dispatch ():void { dispatchEvent(new Event(Event.CHANGE)); } }
      
      







結論:



本質的に、シグナルは同じオブザーバーパターン、つまりIEventDispatcherの代替です。 ライブラリはネイティブではないが、許容レベルであるため、パフォーマンスは低下します。 シグナルを使用すると、それらに関連付けられた他のソリューションのC#からActionScriptへの移行を開始できます。



プラス:

-よりコンパクトなコード



マイナス:

-生産性



All Articles