Jul 30

最近一同事的过多且混乱的if…else,产生了些许话题。正好看<依赖注入那些事儿>文中也说到这事,示例是用策略模式解决的。

我突发奇想,利用AS3的脚本语言的特性实现了类似的解决方案,其实在javascript中,这种用法很常见,其实在AS2及以前的时代,也是这样。
ScriptStrategyImplement.as

package {
	import flash.utils.Dictionary;
	import flash.events.MouseEvent;
	import flash.display.Sprite;

	/*
	 * 利用脚本语言的特性,实现类似策略模式的思想
	 * 用到if…else或switch…case结构处都可尝试用这个实现
	 * 如用MVC框架,可用Command实现,用条件参数(按需加类别标识)做事件常量,注册处理Command后发通知
	 */
	public class ScriptStrategyImplement extends Sprite {
		// 方法存储器
		private var _strategies : Dictionary;
		// 方法名
		private static const STRATEGY : String = "strategy_";
		private static const S_A : String = STRATEGY + "1";
		private static const S_B : String = STRATEGY + "2";
		private var _count : int;

		public function ScriptStrategyImplement() {
			_strategies = new Dictionary();
			// 存储方法,绑定方法名和方法
			_strategies[S_A] = _concreteStrategyA;
			_strategies[S_B] = _concreteStrategyB;

			// 使用演示
			_count = 0;
			stage.addEventListener(MouseEvent.CLICK, clickHandler);
		}

		private function clickHandler(event : MouseEvent) : void {
			_count++;
			_strategyExecute(STRATEGY + String(_count), String(_count));
		}

		private function _concreteStrategyA(value : Object = null) : void {
			trace(value);
		}

		private function _concreteStrategyB(value : Object = null) : void {
			trace(value);
		}

		// 传入方法名,执行对应的方法
		private function _strategyExecute(iName : String, value : Object = null) : void {
			try {
				_strategies[iName](value);
			} catch(error : Error) {
				trace("没有绑定处理方法" + error.message);
			}
			// for (var i:String in _strategies) {
			// if (i == iName) {
			// _strategies[iName](value);
			// break;
			// }
			// }
		}
	}
}

后来有根据describeType的功能写了一版。
ScriptStrategyDescribeTypeImplement.as

package {
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	public class ScriptStrategyDescribeTypeImplement extends Sprite {
		private var  _description : XML;
		// 方法名前缀
		private static const METHOD : String = "method_";
		private var _count : int;

		public function ScriptStrategyDescribeTypeImplement() {
			// 只有该类的public的方法才会写入describeType返回该Class的描述XML中
			_description = describeType(getDefinitionByName(getQualifiedClassName(this)) as Class);
			// 使用演示
			_count = 0;
			stage.addEventListener(MouseEvent.CLICK, clickHandler);
		}

		private function clickHandler(event : MouseEvent) : void {
			_count++;
			_strategyExecute(METHOD + String(_count), String(_count));
		}

		public function method_1(value : Object = null) : void {
			trace(value);
		}

		public function method_2(value : Object = null) : void {
			trace(value);
		}

		// 传入方法名,执行对应的方法
		private function _strategyExecute(mName : String, value : Object = null) : void {
			var method : XMLList = _description.factory.method as XMLList;
			var max : int = method.length() - 1;
			var methodNode : XML;
			for (var i : int = max; i > -1; i--) {
				methodNode = method[i] as XML;
				if (methodNode.@name == mName) this[mName](value);
			}
		}
	}
}

又悲催的发现,现实中几乎用不到,还是if…else和switch…case顺手呀,而且可读性也更高些。

written by panhezeng \\ tags:

©panhezeng for 阿潘道, 2006-2017. 原文地址:http://apsay.com/?p=1323
本文遵循署名-非商业性使用共享协议,转载请注明。

Leave a Reply