从热键系统看分离式的软件设计(三)

先把前两篇的链接收集一下:

  1. 从热键系统看分离式的软件设计(一)
  2. 从热键系统看分离式的软件设计(二)

来做个结尾。这次讲讲抽象按键和统一管理按键。说到统一管理,我第一个就想到在一个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)的固定性,如果要添加新的处理函数,就比较麻烦了。无论如何,这类分离式的设计方式是应当有益的。

RELATED POSTS

One Comment

  1. kunshou says:

    支持一把 很有用的经验

Leave a Reply