从热键系统看分离式的软件设计(三)
先把前两篇的链接收集一下:
来做个结尾。这次讲讲抽象按键和统一管理按键。说到统一管理,我第一个就想到在一个class做完所有的事情,没错,可以尝试这样的方法。比如:
package myvocal.utils.input { import flash.events.EventDispatcher; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import mx.core.Application; /** * it's a singleton object which is used to handle global hot keys. * * capture parse of event flow is used to catch keydown * */ public class CHotKeys extends EventDispatcher { public function CHotKeys() { //TODO: implement function super(null); Application.application.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, true); //Application.application.setFocus(); } private static var owner:CHotKeys; public static function getInstance():CHotKeys { if(owner == null) { owner = new CHotKeys(); } return owner; } /////////////////////////////////////////// /* private var help_func:Function; private var record_func:Function; private var play_func:Function; private var stop_func:Function; private var rewind_func:Function; */ public static const HELP_HK:String = "help_hk"; public static const RECORD_HK:String = "record_hk"; public static const PLAY_HK:String = "play_hk"; public static const STOP_HK:String = "stop_hk"; public static const REWIND_HK:String = "rewind_hk"; private var _hotkeyTemp:IHotKeyTemplate; /** * there is only one IHotKeyTemplate object that is activated */ public function activate(ihotkey:IHotKeyTemplate):void { _hotkeyTemp = ihotkey; } /** * define hot keys and handler them */ private function onKeyDown(event:KeyboardEvent):void { trace(event.keyCode); //event.preventDefault(); switch(event.keyCode) { case Keyboard.F1: //help if(_hotkeyTemp != null) { _hotkeyTemp.hk_help_func(); } event.preventDefault(); break; case Keyboard.F2: //record or stop record if(_hotkeyTemp != null) { _hotkeyTemp.hk_record_func(); } event.preventDefault(); break; case Keyboard.F3: //play or pause if(_hotkeyTemp != null) { _hotkeyTemp.hk_play_func(); } event.preventDefault(); break; case Keyboard.F4: //stop if(_hotkeyTemp != null) { _hotkeyTemp.hk_stop_func(); } event.preventDefault(); break; case Keyboard.F5: //rewind if(_hotkeyTemp != null) { _hotkeyTemp.hk_rewind_func(); } event.preventDefault(); break; } } } }
方法onKeyDown监听Application的按键(注意这里useCapture设true,否则事件流冒泡上去就抓不到了)。为什么要监听Application,那是为了全局监听,即无论focus在哪儿,按键都能响应。onKeyDown里面根据不用需要设计按键和捆绑处理函数。注意,这里的处理函数是抽象的。
整合他们
上面讲到了,处理函数是抽象的。这就是一种间接关系。系统可以灵活的激活不同的处理对象(即activate方法里的_hotkeyTemp),同时也不用担心内存泄漏(这就是为啥不用addEventListener)。对于我的这个项目,只需要为每个state实现IHotKeyTemplate接口,就算添加新的state也不会对其它模块造成影响。不过缺点也是存在的:这种设计在最初是默认接口(IHotKeyTemplate)的固定性,如果要添加新的处理函数,就比较麻烦了。无论如何,这类分离式的设计方式是应当有益的。


支持一把 很有用的经验