命令模式:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么,此时希望用一种松耦合的方式来设计软件,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

说法很复杂,简单来说就是希望真正做事情的对象不要直接被调用,当我们下达一些命令之后, 希望对象已经间接的执行了。这样做的好处是可以解耦,代码可以更为灵活,还可以管理命令,甚至完成命令队列这样的操作。

实现思路

为了实现这种效果,我们需要通过一个函数,创造一个接口对象,调用接口对象的方法,就是调用对象真正的方法。

下面的例子是常规的直接调用对象的方法

 var bindClick = function( button, func ){ //两个参数一个是执行对象,一个是执行的函数
button.onclick = func;
}; var MenuBar = {
refresh: function(){
console.log( '刷新界面' );
}
}; bindClick( button1, MenuBar.refresh ); //不直接写button1.click=function(){} 是因为在改动频繁的开发中,改动起来很麻烦,毕竟谁触发什么事件都是不确定的。

现在我们使用命令模式创建一个接口对象

 var setCommand = function( button, command ){  //command为接口对象
button.onclick = function(){
command.refresh(); //接口对象提供的方法
}
}; var MenuBar = {
refresh: function(){
console.log( '刷新菜单界面' );
}
}; var createCommand = function( obj ){ //创建接口对象的方法
return {
refresh: function(){
obj.refresh();
}
}
}; var menubar = createCommand( MenuBar ); //创建一个接口对象 /*也可以这么写 或者方法放到原型上
var createCommand( obj ){
this.obj=obj;
this.refresh=function(){
this.obj.refresh();
}
} var menubar = new createCommand( MenuBar ); */ setCommand( button1, menubar ); //触发时调用接口对象的方法,接口对象再调用真正对象的方法。

从这里看好像和代理模式有点像,都是提供一个接口,内部做些处理再调用本体,但还是有区别的,代理模式的话代理对象只为一个本体服务,而命令模式中,接口对象就像一个黑盒子,可以依次执行命令,也能撤销命令,一个命令可能可以让不同的对象执行自己的方法,见下面的代码:

 var list=(function(){   //接口对象,这里因为不存在通用的问题,所以直接写了
var arr=[];
return {
add:function(obj){
arr.push(obj);
},
execute:function(){
for(var i=0,l=arr.length;i<l;i++){
arr[i].execute();
}
}
}
})(); list.add( menubar );
list.add( headbar );
list.add( footbar );
list.execute();

上面这段代码就比较清晰了,命令的管理对象中的一个接口,可以执行不同对象的方法,等于导演说一句开机,剩下的人都可以自行其事。

这里我们假定对象都拥有一个execute方法,倘若对象没有一个公共的方法,那也可以给对象加一个,如果通过new的方式创建对象就在原型链上加,如果没有通过new,就直接添加

 //new的方式
menubar=new Menubar();
Menubar.prototype.execute=function(){
this.refresh(); //真正需要执行的方法,下同
}
//直接加
menubar.execute=function(){
this.refresh();
}

撤销操作

撤销操作的实现一般是给命令对象增加一个名为unexecude或者undo的方法,在该方法里执行execute的反向操作。
比如动画,撤销时候回到一开始的位置,那就得记录一开始的位置,点撤销后回到那里;如果是canvas画图这种,撤销就是先清空画布,然后再把记录的命令依次执行,撤销那步除外。实现撤销要看具体情况。

总结

命令模式呢,就是通过一个对象来管理命令(需要执行的指令集合),通过这个对象,可以将原本复杂的对象间的交互变得简单起来。同时因为降低了耦合度,也有利于代码的维护。

javascript设计模式与开发实践阅读笔记(9)——命令模式的更多相关文章

  1. javascript设计模式与开发实践阅读笔记(4)——单例模式

    定义 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 具体来说,就是保证有些对象有且只有一个,比如线程池.全局缓存.浏览器中的window 对象等.在js中单例模式用途很广,比如登录 ...

  2. javascript设计模式与开发实践阅读笔记(8)——观察者模式

    发布-订阅模式,也叫观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 在JavaScript开发中,我们一般用事件模型来替代传统的观察者模式. ...

  3. javascript设计模式与开发实践阅读笔记(7)——迭代器模式

    迭代器模式:指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...

  4. javascript设计模式与开发实践阅读笔记(6)——代理模式

    代理模式:是为一个对象提供一个代用品或占位符,以便控制对它的访问. 代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对 ...

  5. javascript设计模式与开发实践阅读笔记(5)——策略模式

    策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 我的理解就是把各种方法封装成函数,同时存在一个可以调用这些方法的公共函数.这样做的好处是可以消化掉内部的分支判断,使代码效率 ...

  6. javascript设计模式与开发实践阅读笔记(11)—— 模板方法模式

    模板方法模式: 由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类.通常在抽象父类中封装了子类的算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺序.子类通过继承这个抽象类,也继 ...

  7. JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)

    说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...

  8. 《JavaScript设计模式与开发实践》笔记第八章 发布-订阅模式

    第八章 发布-订阅模式 发布-订阅模式描述 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于 ...

  9. JavaScript设计模式与开发实践——读书笔记1.高阶函数(下)

    上部分主要介绍高阶函数的常见形式,本部分将着重介绍高阶函数的高级应用. 1.currying currying指的是函数柯里化,又称部分求值.一个currying的函数会先接受一些参数,但不立即求值, ...

随机推荐

  1. sql server多数据库查询 远程数据库查询

    --创建链接服务器 exec sp_addlinkedserver 'srv_lnk','','SQLOLEDB','服务器地址' exec sp_addlinkedsrvlogin 'srv_lnk ...

  2. 高频交易策略[z]

    Market Order以最高速下市价单(market order)是买方最基本的策略 Looking for Price Discrepancies 这个就是高频统计套利(high frequenc ...

  3. shell脚本批量处理字符串

    上周五运营那边给了一份手机号码的excle,要求查询出所有对应于用户编号的用户的信息.这个时候遇到了一个问题就是,需要查询的用户数量很多,不可能一个一个去查,而excle中的格式又不符合sqlquer ...

  4. php 解析 视频 信息 封面 标题 图片 支持 优酷, 土豆 酷6 56 新浪 qq播客 乐视 乐视

    原文地址:http://www.lianyue.org/2013/2497/ <?php /** * 解析 视频信息 类 * * 支持 优酷, 土豆 酷6 56 新浪 qq播客 乐视 乐视 ** ...

  5. linux服务之X windows

    gnome display manager :gdm window manager :metacity x-server x-client [root@localhost gdm]# xlsclien ...

  6. 使用 IntraWeb (44) - 测试读取 SqLite (三)

    使用数据连接池(TIWDataModulePool). 新建工程时勾选 Pool Data Connections: 新增的 Pool(TIWDataModulePool) 被放在 ServerCon ...

  7. 烧写AT91Bootstrap不能连接SAM-BA的解决方法

    AT91与SAM-BA的连接是由于芯片内有一段固化的代码运行起来后才会检测到目标板并建立连接.    假设现在你烧写了Bootstrap进去,芯片上电后发现有可运行的代码,从而就不执行片内固化的那个代 ...

  8. freeCodeCamp:Find the Longest Word in a String

    找到提供的句子中最长的单词,并计算它的长度. 函数的返回值应该是一个数字. /* 先把字符串 str 转为数组 myarr 将数组myarr中的每个元素长度转换成一个新的数组newarr 将这个数组按 ...

  9. (Python)集合、集合的函数

    本节我们将学习python的另一种数据类型:集合(set) 1.集合(set) 集合在Python中是一种没有重复元素,且无序的数据类型,且不能通过索引来引用集合中的元素 >>> b ...

  10. HTML之表单元素

    A.表单元素都是放在<form></form>标签内的.来看看表单的属性  属性 值 描述 accept MIME_type 规定通过文件上传来提交的文件的类型 accept- ...