JavaScript设计模式七(命令模式)

JavaScript设计模式七(命令模式)

定义:

命令模式是最简单和优雅的模式之一,命令模式中的命令指的是一个执行某些特定事情的指令

使用场景:
有时候需要向某些对象发送请求,但是不知道请求的接受者是谁,也不知道被请求的操作是什么。这种情况需要我们设计发送者和请求的接受者消除彼此的耦合关系。

命令模式的例子

假设我们在编写一个程序,用户界面上至少由数十按钮,因为项目负责,我们让两个程序员参与,一个写样式,一个写点击按钮后的行为,这些行为都封装在对象里面。这里对于绘制按钮的程序员来说,他根本就不知道某个按钮的作用,他只知道这些按钮会被点击,然后触发一些事情。所以这个就很适合用命令模式来把按钮和具体行为解耦合。

<body>
    <button id="btn1">button1</button>
    <button id="btn2">button2</button>
    <button id="btn3">button3</button>
</body>
<script>
    var btn1 = document.getElementById('btn1');
    var btn2 = document.getElementById('btn2');
    var btn3 = document.getElementById('btn3');
</script>

我们上面说了,这些按钮肯定会执行一些操作,我们叫command,执行的动作我们约定调用command对象的execute方法,虽然我们不知道这些命令代表的是啥子,但是负责绘制按钮的程序员也不关心这些,只需要预留好安装命令的接口,command对象自然就知道如何正确的沟通

var setCommand = function(button, command) {
    button.onclick = function() {
        command.execute();
    };
};

然后我们在看那个写交互button的程序员,他写了刷新界面、增加子菜单和删除子菜单这几个功能

var MenuBar = {
    refresh: function() {
        conosle.log('refresh');
    },
};

var SubMenu = {
    add: function() {
        console.log('add');
    },
    del: function() {
        console.log('del');
    }
}

为了让button变得有用,我们需要把这行行为都封装到命令类里面去。

var RefreshMenuBarCommand = function(receiver) {
    this.receiver = receiver;
}

RefreshMenuBarCommand.prototype.execute = function() {
    this.receiver.refresh();
}

var AddSubMenuCommand = function(receiver) {
    this.receiver = receiver;
}

AddSubMenuCommand.prototype.execute = function() {
    this.receiver.add();
}

var DelSubMenuCommand = function(receiver) {
    this.receiver = receiver;
}

DelSubMenuCommand.prototype.execute = function(){
    this.receiver.del();
}

使用方法:

var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar);
var addSubMenuCommand = new AddSubMenuCommand(SubMenu);
var delSubMenuCommand = new DelSubMenuCommand(SubMenu);

setCommand( btn1, refreshMenuBarCommand );
setCommand( btn2, addSubMenuCommand );
setCommand( btn3, delSubMenuCommand );

这样子做我们可以看到请求的发送者和请求的接受者是耦合开的。可以随意改变,随意组合

JavaScript中的命令模式

我不知道大家看了上面的代码怎么想的,我感觉很奇怪,至少我们实际中不会这么写代码。我们的目的是给对象去了一个execute的方法,为了达到这个目的,我们引入了command对象和receiver两个角色。

var bindClick = function(button, func) {
    button.click = func;
}
var MenuBar = {
    refresh: function() {
        conosle.log('refresh');
    },
};

var SubMenu = {
    add: function() {
        console.log('add');
    },
    del: function() {
        console.log('del');
    }
}
bindClick(btn1, MenuBar.refresh);
bindClick(btn2, SubMenu.add);
bindClick(btn3, SubMenu.del);

上一节中的实现方式是模拟的面向对象的方式来实现的,命令模式把过程化的请求封装到了command对象的execute方法中,通过封装来把运算包装。
命令模式的由来其实是回调函数面向对象的一个替代品。
JavaScript作为函数式语言,和策略模式一样,命令模式早就融入到了JavaScript中,运算块不一定要封装到command对象中,封装到函数中也是也可以的,因为函数可以作为参数到处传递,接下来我们看如何利用闭包来实现命令模式

var setCommand = function(button, func) {
    button.onclick = function() {
        func();
    };
};

var MenuBar = {
    refresh: function() {
        conosle.log('refresh');
    },
};

var RefreshMenuBarCommand = function(receiver) {
    return function() {
        receiver.refresh();
    }
}

var refershMenuBarCommand = RefreshMenuBarCommand(MenuBar);
setCommand(btn1, refershMenuBarCommand)

命令模式除了执行命令外,还是撤销命令、重做命令等等,所以我们把上面的代码稍微修改下

var setCommand = function(button, command) {
    button.onclick = function() {
        command.execute();
    };
};

var RefreshMenuBarCommand = function(receiver) {
    return {
        execute: function() {
            receiver.refresh();
        }
    }
}

var refershMenuBarCommand = RefreshMenuBarCommand(MenuBar);
setCommand(btn1, refershMenuBarCommand);

至于撤销和重做是类似的

宏命令

宏命令是指一组命令,通过宏命令,我们执行一批命令,例如我们需要点击一下app,自动把门关上,顺便打开电脑,登录QQ

我们第一步,当然是创建这一个个命令拉

var closeDoorCommand = {
    execute: function(){
        console.log('close door');
    }
}

var openPCCommand = {
    execute: function() {
        console.log('open pc');
    }
}

var openQQCommand = {
    execute: function() {
        console.log('open qq');
    }
}

然后定义下宏命令,增加一个add方法把子命令添加进去,调用宏命令的execute方法时,会迭代刚才添加的子命令,并以此执行

var MacroCommand = function() {
    return {
        commandsList: [],
        add: function(command) {
            this.commandsList.push(command);
        },
        execute: function(){
            for(var i = 0; i< this.commandsList.length; i++) {
                this.commandsList[i].execute();
            }
        }
    }
}

var macroCommand = MacroCommand();
macroCommand.add(closeDoorCommand);
macroCommand.add(openPCCommand);
macroCommand.add(openQQCommand);

macroCommand.execute();
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,717评论 2 17
  • 工厂模式 单体模式 模块模式 代理模式 职责链模式 命令模式 模板方法模式 策略模式 发布-订阅模式 中介者模式 ...
    HelloJames阅读 1,004评论 0 6
  • 目录 本文的结构如下: 什么是命令模式 为什么要用该模式 模式的结构 代码示例 优点和缺点 适用环境 模式应用 总...
    w1992wishes阅读 1,095评论 2 9
  • 【学习难度:★★★☆☆,使用频率:★★★★☆】直接出处:命令模式梳理和学习:https://github.com/...
    BruceOuyang阅读 819评论 0 3
  • “看,你都不注意身体,总熬夜,都秃了吧…” “看,你都不懂爱,不珍惜,都离婚了吧…” “看,你被生活折磨的,都信佛...
    呆小萌看社会阅读 184评论 0 0