“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。
实例:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#div1{
position: fixed;left:50%;top:50%;width: 50px;height: 50px;background: red;
}
</style>
<script type="text/javascript">
//调用者,向上命令
var MoveUp = function(reciever){
this.reciever = reciever;
};
MoveUp.prototype.execute = function(){
this.reciever.move(0,-10);
}
MoveUp.prototype.undo = function(){
this.reciever.move(0,10);
}
//调用者,向下命令
var MoveDown = function(reciever){
this.reciever = reciever;
};
MoveDown.prototype.execute = function(){
this.reciever.move(0,10);
}
MoveDown.prototype.undo = function(){
this.reciever.move(0,-10);
}
//调用者,向左命令
var MoveLeft = function(reciever){
this.reciever = reciever;
};
MoveLeft.prototype.execute = function(){
this.reciever.move(-10,0);
}
MoveLeft.prototype.undo = function(){
this.reciever.move(10,0);
}
//调用者,向右命令
var MoveRight = function(reciever){
this.reciever = reciever;
};
MoveRight.prototype.execute = function(){
this.reciever.move(10,0);
}
MoveRight.prototype.undo = function(){
this.reciever.move(-10,0);
}
//接受者,真正执行操作的类
var Reciever = function(){};
Reciever.prototype.move = function(left,top){
var div = document.getElementById('div1');
var left = div.offsetLeft+left;
var top = div.offsetTop+top;
div.style.setProperty("left",left+"px");
div.style.setProperty("top",top+"px");
}
//装饰者,添加记录操作的行为
var UndoDercorator = function(command){
this.command = command;
}
UndoDercorator.undoStack = [];
UndoDercorator.prototype.execute = function(){
UndoDercorator.undoStack.push(this.command);
this.command.execute();
}
UndoDercorator.prototype.undo = function(){
this.command.undo();
}
window.onload = function(){
var reciever = new Reciever();
var left = document.getElementById('left');
var right = document.getElementById('right');
var up = document.getElementById('up');
var down = document.getElementById('down');
var undo = document.getElementById('undo');
var moveLeft = new UndoDercorator(new MoveLeft(reciever));
var moveRight = new UndoDercorator(new MoveRight(reciever));
var moveUp = new UndoDercorator(new MoveUp(reciever));
var moveDown = new UndoDercorator(new MoveDown(reciever));
left.addEventListener('click',function(){
moveLeft.execute();
})
right.addEventListener('click',function(){
moveRight.execute();
})
up.addEventListener('click',function(){
moveUp.execute();
})
down.addEventListener('click',function(){
moveDown.execute();
})
undo.addEventListener('click',function(){
if(UndoDercorator.undoStack.length>0){
var cmd = UndoDercorator.undoStack.pop();
cmd.undo();
}else{
alert('不能再回退了');
}
})
}
</script>
</head>
<body>
<div id = "div1"></div>
<input type="button" value="left" id="left">
<input type="button" value="right" id="right">
<input type="button" value="up" id="up">
<input type="button" value="down" id="down">
<input type="button" value="down" id="undo">
</body>
</html>