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

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

实现思路

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

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

 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. javascript 的 梯子

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  2. Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  3. windows 10环境下 使用 msys2 + vs code 配置 c++ 的编译环境

    不太多描述 msys2 与  vs code  ,既然你需要安装 一种语言的编译环境了 ,你肯定对这两个不陌生: 1. 先安装msys2; (下载多少位的msys2就安装多少位的 mingw,本人安装 ...

  4. LeetCode.4 两个有序数组的中位数问题

    这道题是那种典型的有显而易见的解法, 但是想要达到较优的时间复杂度的话就不是这么好做的题目. 我来说说我自己的思考过程 : 首先最先想到的是 O(m + n) 的解法, 也就是利用归并排序的归并将两个 ...

  5. linux笔记-硬链接和符号链接

    硬链接:指多个路径名(不同目录下的不同文件名)指向同一个硬盘数据,用其中的随便哪个文件打开修改数据,都会在其他文件打开中更新, 原因就是硬链接和“原”文件inode相同,每增加或者删除一个链接,链接计 ...

  6. 怎样按xc或yc转正视图

    extern void create_view(void) { tag_t wcs_id,matrix_id; double mtx[9],wcs_pt[3]; double x_axis[3]={1 ...

  7. asp控件Repeater运用

    双层repeater嵌套 <asp:Repeater ID="rpt_dataRepeatgroup" runat="server" OnItemData ...

  8. sublim text3 配置

    喜欢用sublime,但每次换环境都要重新百度下配置,太麻烦,故在此把自己喜欢的配置记录下来 sublime text2 可以直接在设置里改,但sublime text3不能直接在设置中改值,只能在s ...

  9. HDU 5023 A Corrupt Mayor's Performance Art (据说是线段树)

    题意:给定一个1-n的墙,然后有两种操作,一种是P l ,r, a 把l-r的墙都染成a这种颜色,另一种是 Q l, r 表示,输出 l-r 区间内的颜色. 析:应该是一个线段树+状态压缩,但是我用s ...

  10. 天气预报数据API

    http://www.weather.com.cn/data/cityinfo/101010100.html//过期: http://api.36wu.com/Weather/GetMoreWeath ...