javascript设计模式学习之九——命令模式
一、命令模式使用场景及定义
命令模式常见的使用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道请求的具体操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求的发送者和请求接受者可以解除彼此之间的耦合关系。
命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分隔开。请求的一方不必知道接收请求一方的接口,更不必知道请求是怎么被接收的,以及操作是否被执行,何时被执行,以及是如何执行的。
命令模式使得请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。由于对象的生命周期在程序运行期间是一直存在的,因此可以在需要的任何时间执行。
适用场景:
1.系统需要将请求调用者和请求接收者解耦,使得二者不直接交互。
2.系统需要在不同的时刻指定请求,将请求排队和执行请求。
3.系统需要支持命令的撤销(undo)和恢复(redo)操作。
4.系统需要将一组操作组合在一起,即支持宏命令。
这些优点归根结底在于我们将命令封装成了对象,
命令模式中,命令的请求发出者不直接与命令的接收者交互,而是与命令对象交互。
命令对象一般持有接收者(java中,接收者一般作为命令对象的一个属性);javascript中接收者可以作为函数的参数传递。
通过命令对象将命令请求发出者与命令接收者以松耦合的方式联系起来,因为命令对象的生命周期几乎是永久的,除非我们主动去回收它,因此命令对象的生命周期跟请求初始发生的时间无关。可以进行命令的排队、重做、取消等操作。
二、java中的命令模式
参见博客:http://blog.csdn.net/jason0539/article/details/45110355
角色:
Command 定义命令的接口,声明execute等方法;
ConcreteConmand 实现命令接口,通常会持有接收者,并调用接收者的功能来实现相应的功能。
Receiber 接口者,命令真正的执行对象。
Invoker 通常会持有命令对象,可以持有很多得命令对象,相当于使用命令对象的入口;可以对命令对象进行排队等操作。
Clinet 创建具体的命令对象,并为其设置接收者。从这个角度上来说,称之为“装配者”更为贴切。
java命令模式的使用案例(模拟对计算机的操作有开机,关机,换台等命令)
package com.bobo.shejimoshi;
//命令接收者Receiver,要是真正执行命令的对象
public class Tv {
public int currentChannel=;
public void turnOn(){
System.out.println("the tv is on");
}
public void turnOff(){
System.out.println("the tv is off");
}
public void changeChannel(int channel){
this.currentChannel=channel;
System.out.println("Now tv channel is "+channel);
}
}
package com.bobo.shejimoshi;
//执行命令的抽象接口
public interface Command {
void execute();
}
package com.bobo.shejimoshi;
//命令接口的实现对象
public class CommandOn implements Command{
private Tv myTv;
public CommandOn(Tv tv){
myTv=tv;
}
@Override
public void execute() {
// TODO Auto-generated method stub
myTv.turnOn();
} }
package com.bobo.shejimoshi;
//命令接口的实现对象
public class CommandOff implements Command{
private Tv myTv;
public CommandOff(Tv tv){
myTv=tv;
}
@Override
public void execute() {
myTv.turnOff();
} }
package com.bobo.shejimoshi;
//命令接口的实现对象
public class CommandChange implements Command{
private Tv myTv;
private int channel;
public CommandChange(Tv tv,int channel){
myTv=tv;
this.channel=channel;
}
public void execute(){
myTv.changeChannel(channel);
} }
package com.bobo.shejimoshi;
//可以看做是遥控器Invoker,作为使用命令对象的入口,可以持有很多的命令对象
//根据应用场景,invoker可以进行命令的排队等
public class Control {
private Command onCommand,offCommand,changeChanelCommand;
public Control(Command on, Command off,Command channel){
onCommand=on;
offCommand=off;
changeChanelCommand=channel;
} public void turnOn(){
onCommand.execute();
} public void turnOff(){
offCommand.execute();
} public void changeChannel(){
changeChanelCommand.execute();
} }
package com.bobo.shejimoshi;
//测试类client,
public class Client { public static void main(String[] args) {
//命令接收者receiver
Tv myTv=new Tv();
CommandOn on=new CommandOn(myTv);
CommandOff off=new CommandOff(myTv);
CommandChange chanel=new CommandChange(myTv,);
Control control=new Control(on,off,chanel);
//开机
control.turnOn();
//关机
control.turnOff();
//调台
control.changeChannel(); } }
三、javascript中的命令模式
javascript作为函数作为一等公民的语言,命令模式已经融入到语言的设计中。在面向对象的语言如java中,命令模式的接收者被当做command对象的属性保存起来,同时约定执行命令的操作调用command.execute方法,在javascript中,接收者可以封闭在闭包产生的环境中,执行命令的操作可以更加简便,仅仅执行回调函数即可。并且运算块可以封装在command.execute方法中,也可以封装在普通函数中。
//命令模式的学习
var tv = (function() {
var turnOn = function() {
console.log('打开电视机');
};
var turnOff = function() {
console.log('关闭电视机');
};
var changeChannel = function(channel) {
console.log('当前电视频道为' + channel);
};
return {
'turnOn': turnOn,
'turnOff': turnOff,
'changeChannel': changeChannel
}
})();
var TurnOnCommand = function(receiver) {
return function() {
receiver.turnOn();
}; };
var TurnOffCommand = function(receiver) {
return function() {
receiver.turnOff();
}; };
var changeChannelCommand = function(receiver, channel) {
return function() {
receiver.changeChannel(channel);
}; }; //测试
var setCommand = function(button, func) {
button.onclick = function() {
func();
};
}; var button = document.getElementById('btn');
var turnOnCmd = TurnOnCommand(tv);
var turnOffCmd = TurnOffCommand(tv);
var changeChannelCmd = changeChannelCommand(tv, );
setCommand(button, changeChannelCommand); //可以将命令加入队列,依次执行
var commandsQueue=[];
commandsQueue.push(changeChannelCmd);
commandsQueue.push(turnOnCmd);
commandsQueue.push(turnOffCmd); while(command=commandsQueue.shift()){
command();
}
当然,考虑到除了执行命令之外,将来还可能提供撤销等操作,因此最好还是把执行函数改为调用execute方法,代码如下:
//实现单例模式
var tv=(function(){
var turnOn=function(){
console.log('打开电视机');
};
var turnOff=function(){
console.log('关闭电视机');
};
var changeChanel=function(channel){
console.log('当前电视频道为:'+channel);
};
return{
turnOn:turnOn,
turnOff:turnOff,
changeChanel:changeChanel
};
})(); var TurnOnCommand=function(receiver){
return {
execute:function(){
receiver.turnOn();
}
};
};
var TurnOffCommand=function(receiver){
return {
execute:function(){
receiver.turnOff();
}
};
};
var ChangeChanelCommand=function(receiver,channel){
return {
execute:function(){
receiver.changeChanel(channel);
}
};
}; function setCommand(btn,command){
btn.addEventListener('click',function(){
command.execute();
});
}
var turnOnCmd=new TurnOnCommand(tv);
var turnOffCmd=new TurnOffCommand(tv);
var changeChanelCmd=new ChangeChanelCommand(tv,);
var btn=document.getElementById('btn');
setCommand(btn,changeChanelCmd);
通过实践,发现javascript中的命令模式:
执行命令的操作大多数时候不是以命令对象的方式存在,很可能就是一个回调函数,从表面看起来甚至不太注意到这是命令模式。
在自己封装的动画类中,每一次执行动画的命令操作就是一个回调函数(函数保存有命令执行者的引用,不论是通过函数参数访问到命令执行者,或者是像动画类中可通过this访问到命令执行者),通过数组将动画执行操作进行排队;
在自己封装的表单验证插件中,每一次执行验证的操作实际上就是formField对象的一个方法,在合适的时机(如表单提交时)调用该方法。
javascript设计模式学习之九——命令模式的更多相关文章
- javascript设计模式详解之命令模式
每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...
- javascript设计模式学习之十——组合模式
一.组合模式定义及使用场景 组合模式将对象组合成树形结构,用以表示“部分—整体”的层次结构,除了用来表示树形结构之外,组合模式还可以利用对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性. ...
- Javascript设计模式学习三(策略模式)
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换.目的:将算法的使用和算法的实现分离开来.比如: if(input == 'A'){ return 1; } if(input == ...
- javascript设计模式详解之策略模式
接上篇命令模式来继续看下js设计模式中另一种常用的模式,策略模式.策略模式也是js开发中常用的一种实例,不要被这么略显深邃的名字给迷惑了.接下来我们慢慢看一下. 一.基本概念与使用场景: 基本概念:定 ...
- 设计模式学习系列6 原型模式(prototype)
原型模式(prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个新对象的时候根本无需知道任何创建细节,只需要请求圆形对象的copy函数皆可. 1 ...
- Java设计模式(22)命令模式(Command模式)
Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体 ...
- C#设计模式之11:命令模式
C#设计模式之11:命令模式 命令模式 命令模式用来解决一些复杂业务逻辑的时候会很有用,比如,你的一个方法中到处充斥着if else 这种结构的时候,用命令模式来解决这种问题就会让事情变得简单很多. ...
- JavaScript设计模式学习笔记
1 JavaScript设计模式深入分析 私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量. 特权属性和方法:创建属 ...
- Javascript设计模式学习一
学习Javascript设计模式之前,需要先了解一些相关知识,面向对象的基础知识.this等重要概念,以及掌握一些函数式编程的技巧. Js多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...
随机推荐
- angJs使选中的li背景颜色不同
<!doctype html><html><head><meta charset="UTF-8"><title>test ...
- github 向导/介绍
环境:windows 7 64bit 阅读了http://guides.github.com的教程. 流程 git是协作版本管理的一种方法.工作流程是在一个主线基础上发展分支(branch),最后并入 ...
- VR制作的规格分析
因为UE4的演示资源更丰富一些,我这边把UE4的有代表性的演示都跑了一遍,同时也通过Rift确认效果,和里面的资源制作方式. 首先,UE4是基于物理渲染的引擎,大部分都是偏向图像真实的.使用的材质 ...
- 关于在TP的各类标签中的注意事项
name的位置上的变量是不用加$的 value位置上的变量是要加$的 <eq name="volist.id" value="$Think.post.id" ...
- ExtJS笔记2 Class System
For the first time in its history, Ext JS went through a huge refactoring from the ground up with th ...
- php面向对象之__toString()
似曾相识,在php面向对象编程之魔术方法__set,曾经介绍了什么是魔术方法,这一章又介绍一个魔术方法__tostring(). __toString()是快速获取对象的字符串信息的便捷方式,似乎魔术 ...
- BadgeView的使用介绍
在现在大部分的信息发布类应用,都有这样的一个功能:当后台数据更新,比如有系统消息或者是用户间有互动的时候,通过在控件上显示一个小红点来提示用户有新的信息.一般来说,这种业务需求,我们可以在布局文件中隐 ...
- NSURLSession
参考文章1, apple文档 一.NSURLSessionConfiguration 介绍:分别配置每一个 session 对象.(NSURLConnection 很难做到) 分类: 1) defau ...
- Redis-秒杀场景应用
Redis Util实现 package test.jedis; import java.util.List; import java.util.Set; import redis.clients.j ...
- php-- memcache 与 memcached支架的区别与共同点 个人整理
首先声明:memcache 与 memcached 之间没有关系 1.概念相似 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载. m ...