命令模式

概念描述

命令模式(Command): 将请求与实现解耦并封装成独立的对象,从而使不同的请求对客户端的实现参数化

示例代码

命令模式我们可以看成是将创建模块的逻辑封装在一个对象里,这个对象提供一个参数化的请求接口,通过调用这个接口并传递一些参数实现调用命令对象内部中的一些方法。

对于命令模式来说,请求部分很简单,只需要按照给定的参数格式书写指令即可,所以实现部分封装才是重点,因为它要为请求部分提供所需方法。

下面我们来看一个具体的例子,我们通过命令模式来封装一个画布对象并实现调用命令对象在页面上画出一个长方形。

//实现对象
var CanvasCommand=(function(){
//获取canvas
var canvas=document.getElementById('canvas'),
//canvas元素的上下文引用对象缓存在命令对象的内部
ctx=canvas.getContext('2d');
//内部方法对象
var Action={
//填充色彩
fillStyle:function(c){
ctx.fillStyle=c;
},
//填充矩形
fillRect:function(x,y,width,height){
ctx.fillRect(x,y,width,height);
},
//描边色彩
strokeStyle:function(c){
ctx.strokeStyle=c;
},
//描边矩形
strikeRect:function(x,y,width,height){
ctx.strokeRect(x,y,width,height); },
//填充字体
fillText:function(text,x,y){
ctx.fillText(text,x,y);
}, //开启路径
beginPath:function(){
ctx.beginPath();
},
//移动画笔触点
moveTo:function(x,y){
ctx.moveTo(x,y);
},
//画笔连线
lineTo:function(x,y){
ctx.lineTo(x,y);
},
//绘制弧线
arc:function(x,y,r,begin,end,dir){
ctx.arc(x,y,r,begin,end,dir);
},
//填充
fill:function(){
ctx.fill();
},
//描边
stroke:function(){
ctx.stroke();
}
}
return {
//命令接口
excute:function(msg){
//如果没有命令直接返回
if(!msg){
return;
}
//如果命令是一个数组,遍历执行多个命令
if(msg.length){
for(var i=0;i<msg.length;i++)
arguments.callee(msg[i]);
}else{
//执行一个命令
msg.param=Object.prototype.toString.call(msg.param)==="[object Array]"?msg.param:[msg.param];
Action[msg.command].apply(Action,msg.param);
}
}
}
})()

我们来调用一下在页面画一个红色的矩形

CanvasCommand.excute([
{command:'fillStyle',param:'red'},
{command:'fillRect',param:[20,20,250,150]}
])

我们看到现在有了这个对象,任何人想绘制图形都不需要依赖canvas了只要按照命令对象结构给出的命令格式,写一条命令即可

实例代码

那么在除了画布外在其他场景我们还能使用命令模式做什么呢?其实我们还可以使用命令模式实现自由的创建视图。

既然我们要做一个自由化创建的视图,那么我们肯定要动态展示不同的模块,所以创建元素这一需求就是变化的,因此创建元素方法、展示方法应该都被命令化

//命令实现模块
var viewCommand=(function(){
//方法集合
var Action={
//创建视图方法
create:function(){},
//展示视图方法
display:function(){}
} return function excute(){}
})();

我们的命令对象框架已经搭建出来了,那么我们就要开始实现命令对象中的每一个方法了

由于创建视图的过程中如果单纯使用DOM操作拼凑页面的开销实在有些大,所以我们用格式化字符串模块来创建我们的视图页面

var viewCommand=(function(){
var Action={
create:function(data,view){
//解析数据如果是一个数组
if(data.length){
//遍历数组
for(var i=0;i<data.length;i++){
//将格式化之后的字符串缓存到html中
html+=formteString(tpl[view],data[i])
}
}else{
//直接格式化字符串缓存到html中
html+=formteString(tpl[view],data)
}
},
display:function(container,data,view){
if(data){
//根据指定数据创建视图
this.create(data,view);
}
document.getElementById('container').innerHTML=html;
//展示后清空缓存的字符串
html='';
}
}
var tpl={
product:[
//展示图片结构模板
'<div>',
'<img src="{#src#}"/>',
'<p>{#text#}</p>',
'</div>'
].join(''),
//展示标题结构模板
title:[
'<div class="title">',
'<div class="main">',
'<h2>{#title#}</h2>',
'<p>{#tips#}</p>',
'</div>',
'</div>'
].join('')
}
//格式化字符串缓存字符串
html='';
function formteString(str,obj){
return str.replace(/\{#(\w+)#}/g,function(match,key){
return obj[key]
})
}
命令接口
return function excute(msg){
//解析命令,如果msg.param不是数组则将其转化为数组
msg.param=Object.prototype.toString.call(msg.param)==="[object Array]"?
msg.param:[msg.param];
Action[msg.command].apply(Action,msg.param) }
})();

好了现在我们的命令对象已经创建好了,我们来测试一下

//模拟图片展示数据,标题展示数据
var productData=[
{src:'img/HBuilder.png',text:'1'},
{src:'img/HBuilder.png',text:'2'},
{src:'img/HBuilder.png',text:'3'}],
titleData={title:'HBuilder',tips:'Hello HBuilder'}; //展示标题模块
viewCommand({
command:'display',
param:['title',titleData,'title']
})

//展示多张图片
viewCommand({
command:'display',
param:['product',productData,'product']
})

//创建图片
viewCommand({
command:'create',
param:[{src:'img/HBuilder.png',text:'Hello HBuilder'},'product']
}) //展示多张图片
viewCommand({
command:'display',
param:['product',productData,'product']
})

总结

命令模式是将执行的命令封装,解决命令的发起者与命令的执行者之间的耦合。每一条命令实质上是一个操作。

命令的使用者不必要了解命令的执行者(命令对象)的命令接口使如何实现的、命令是如何接受的。命令是如何执行的。所有的命令都被存储在命令对象中

命令模式的优点:

命令模式的优点是解决命令使用者之间的耦合。新的命令很容易加入到命令系统中供使用者使用。命令的使用具有一致性,多数的命令在一定程度上是简化操作方法的使用。

命令模式的缺点:

命令模式是对一些操作的封装,这就造成每执行一次操作就要调用命令对象增加了系统的复杂度

也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

欢迎转载,转载请注明作者,原文出处。

再起航,我的学习笔记之JavaScript设计模式21(命令模式)的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  2. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

  3. 再起航,我的学习笔记之JavaScript设计模式11(外观模式)

    经过一段时间的学习与分享,我们对创建型设计模式已经有了一定的认识,未来的一段时间里我们将展开新的篇章,开始迈入结构性设计模式的学习. 结构性设计模式与创建型设计模式不同,结构性设计模式更偏向于关注如何 ...

  4. 再起航,我的学习笔记之JavaScript设计模式14(桥接模式)

    桥接模式 桥接模式(Bridge): 在系统沿着多个维度变化的同时,又不增加其复杂度并已达到解耦 从定义上看桥接模式的定义十分难以理解,那么我们来通过示例来演示什么是桥接模式. 现在我们需要做一个导航 ...

  5. 再起航,我的学习笔记之JavaScript设计模式17(模板方法模式)

    模板方法模式 由模板方法模式开始我们正式告别结构型设计模式,开始行为型设计模式的学习分享 行为型设计模式用于不同对象之间职责划分或算法抽象,行为型设计模式不仅仅涉及类和对象,还涉及类或对象之间的交流模 ...

  6. 再起航,我的学习笔记之JavaScript设计模式20(策略模式)

    策略模式 策略模式(Strategy):将定义的一组算法封装起来,使其相互之间可以替换.封装的算法具有一定的独立性,不会随客户端变化而变化. 其实策略模式在我们生活中可应用的地方还是比较多的,比如在商 ...

  7. 再起航,我的学习笔记之JavaScript设计模式22(访问者模式)

    访问者模式 概念介绍 访问者模式(Visitor): 针对于对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法 解决低版本IE兼容性 我们来看下面这段代码,这段代码,我们封装了一个绑定 ...

  8. 再起航,我的学习笔记之JavaScript设计模式24(备忘录模式)

    备忘录模式 概念介绍 备忘录模式(Memento): 在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态. 简易分页 在一般情况下我们需要做 ...

  9. 再起航,我的学习笔记之JavaScript设计模式25(迭代器模式)

    迭代器模式 概念介绍 迭代器模式(Iterator): 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素. 迭代器 程序中的循环是一种利器,循环语句也使我们程序开发更简洁高效,但是有时一遍 ...

随机推荐

  1. 云计算——Google App Eng…

    云计算--Google App Engine(一) 编者:王尚 2014.04.12 20:20 介绍:Google App Engine提供一套开发组件让用户轻松的在本地构建和调试网络应用,之后能让 ...

  2. 【新发现】不用苹果开发账号就能申请ios证书真机调试

    虽然xcode现在可以免证书进行测试了,但众多跨平台开发者,如果还没注册苹果开发者账号. 想安装到自己非越狱手机测试是无能为力了. 不过新技术来了,只需要普通免费的苹果账号无需付费成为开发者就可以申请 ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(999)-如何使用这个系统来开发?

    前言 这篇文本讲述了这个框架的使用方式,及一些疑问的答疑,更加精准的使用这个框架来建立功能 经过几个版本的迭代,系统使用更加方便,代码更加简洁也更加的智能,所以之前61节的文章也需要重新编排 对项目的 ...

  4. Struts2框架入门

    1.1 Struts2概述: 是一个遵循WEB层规范的MVC设实现,该框架基本上借鉴了WebWork框架的体系结构,只吸收了少部分Struts1的优点.是目前JAVA EE项目中WEB层事实上的工业标 ...

  5. angular学习(一)-- Expression

    1.1 表达式:Expression 在AngularJS中,表达式是一种类似于模板引擎的语法, 可以在书写的位置 "输出" 数据. 基本使用 表达式写在双大括号内:{{ expr ...

  6. shell 变量的使用

    变量定义 name="xiaoming"; age=12: 变量名和等号之间不能有空格,否则会报错,同时变量名的命名和其他语言的命名规则基本一样 首个字符必须为字母(a-z,A-Z ...

  7. 社群系统ThinkSNS + 移动端研发周报

    社群系统"ThinkSNS+"对比ThinkSNS V4系列,ThinkSNS V4系列的产品规划主要偏重于企业服务应用,注重功能的覆盖面和用户关系的逻辑处理.Thin社群系统kS ...

  8. KMS注册

    --KMS注册 -------------2014/03/25 --Read this First http://social.technet.microsoft.com/wiki/contents/ ...

  9. python ——面向对象进阶

    1.staticmethod和classmethod staticmethod  静态方法: 让类里的方法,直接被类调用,就像正常的函数一样 宝宝,男 博博,女 海娇,男 海燕,女 海东,男 海峰,男 ...

  10. win10 + Debian9.1双系统安装笔记

    今天去163镜像上下载了"linuxmint-18.2-cinnamon-64bit.iso"和win10安装了双系统,感觉比在桌面方面十分不错,下面mark一下自己安装过程中的总 ...