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多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...
随机推荐
- Apache Spark技术实战之1 -- KafkaWordCount
欢迎转载,转载请注明出处,徽沪一郎. 概要 Spark应用开发实践性非常强,很多时候可能都会将时间花费在环境的搭建和运行上,如果有一个比较好的指导将会大大的缩短应用开发流程.Spark Streami ...
- DS实验题 最大最小
题目: 算法设计: 计算最小值算法: 设置一个flag,flag为1的时候代表遇到*号: 遇到数字时: flag为0进栈: flag为1的时候,从栈顶提出一个元素和当前元素运算,结果进栈 最后对栈进行 ...
- artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
/*! artDialog v6.0.2 | https://github.com/aui/artDialog */ 将页面某一隐藏的 div 的 html 内容传到 artdialog 的弹窗中,并 ...
- php thread
1-include('w_fun.php');页面已经在执行,则修改include中的函数,倒置旧页面不受影响:新页面生效:2-time 轮流 echo ' <script> windo ...
- Machine Learning in Action -- 回归
机器学习问题分为分类和回归问题 回归问题,就是预测连续型数值,而不像分类问题,是预测离散的类别 至于这类问题为何称为回归regression,应该就是约定俗成,你也解释不通 比如为何logistic ...
- delphi 数组类型与数组指针的巧妙利用
{本例通过存取结构, 慢慢引入了数组类型与指针的一些使用方法; 其中六个小例子的测试内容和结果都是一样的. ---------------------------------------------- ...
- nginx生产配置
user www www; worker_processes 8; error_log /data/logs/nginx_error.log crit; pid /usr/local/webserve ...
- PHP数据库基础
PHP数据库基础: 1.varchar:字符串,用于姓名班级,地址等,地址一般长50,姓名长20 2.int:整数,用于成绩,序号等 3.float:小数 4.bit:布尔型,用于性别等 5.时间也用 ...
- 记录下 QT Linux 静态编译遇到的坑
Qt下静态编译Qt,根据我的经验,如果按照Windows下那种直接拿官方sdk安装之后的文件来编译是行不通的,需要直接下载Qt的source包,目前诺基亚的源码叫做qt-everywhere-open ...
- php--yii2框架错误提示
if($code!=200){ $user=new UserAuth(); $user->mobile=$register['mobile']; $user->password=md5($ ...