林秀栋的技术博客

设计模式(十二) 命令模式

//请求与实现解耦
//比如每个模块结构差不多,只是图片数量不同
//可用该模式,传入相应数据生成相应数量图片

var viewCommand = (function(){
	//结构模板
	var tpl = {
			product: [
				'<div>',
					'<img src="{#src#}"/>',
				'</div>'
			].join(''),
			title: [
				'<div>',
					'<p>{#tips#}</p>',
				'</div>'
			].join('')
		},
		html = '';
	//格式化字符串,比如<p>{#tips#}</p>传入{tips:1}变成<p>1</p>
	function formateString(str, obj){
		return str.replace(/\{#(\w+)#\}/g, function(match, key){
			return obj[key];
		})
	}
	//方法集合
	var Action = {
		//创建方法
		create: function(data, view){
			//解析数组,把数据格式化为字符串并缓存在html中
			//如果数据是数组
			if(data.length){
				for(var i = 0, len = data.length; i < len; i++){
					html += formateString(tpl[view], data[i]);
				}
			}else{
				html += formateString(tpl[view], data);
			}
		},
		//展示方法
		display: function(container, data, view){
			if(data){
				this.create(data, view);
			}
			document.getElementById(container).innerHTML = html;
			html = '';
		}
	}
	//命令接口
	return function excute(msg){
		//由于apply要求第二个参数为数组,所以先判断是否为数组
		msg.param = Object.prototype.toString.call(msg.param) === "[object Array]" ?
						msg.param : [msg.param];
		//由于Action内部的方法可能调用this,为保证this指向正确,这里传入Action
		Action[msg.command].apply(Action, msg.param);
	}
})();

var productData = [
		{
			src: '../1.jpg'
		},{
			src: '../2.jpg'
		}
	],
	titleData = {
		tips: 'it is a demo'
	};
viewCommand({
	command: 'display',
	param: ['demo_title', titleData, 'title']
})
viewCommand({
	command: 'display',
	param: ['demo', productData, 'product']
})

//canvas绘图操作繁琐,也可使用命令模式封装