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

应用场景:有时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道被请求的操作是什么,此时希望用一种

松解耦的方式来设计软件,使得请求发送者和请求接受者能够消除彼此之间的耦合关系。

一个简单JavaScript例子:

  1 <!DOCTYPE html> 
  2 <html lang="en"> 
  3 <head> 
  4     <meta charset="UTF-8"> 
  5     <title>命令模式</title> 
  6     <style> 
  7         body{ 
  8             padding:  0; 
  9             margin: 0; 
 10         } 
 11         .ball{ 
 12             position: absolute; 
 13             background: #000; 
 14             width: 50px; 
 15             height: 50px; 
 16             top:  200px; 
 17         } 
 18     </style> 
 19 </head> 
 20 <body> 
 21     <div id="ball" class="ball"></div> 
 22     输入小球移动后的位置:<input type="text" id="pos"> 
 23     <button id="moveBtn">开始移动</button> 
 24     <button id="cancelBtn">cancel</button> 
 25     <script> 
 26  
 27         // 营运策略模式封装一系列缓动算法 
 28         // t:已消耗的时间 b:小球的原始位置   c:小球的目标位置  d:动画持续的总时间 
 29         // 返回当前位置 
 30         var tween = { 
 31             linear: function(t, b, c, d) { 
 32                 return c*t/d + b; 
 33             }, 
 34             easeIn: function(t, b, c, d) { 
 35                 return c * (t /= d) * t + b; 
 36             }, 
 37             strongEaseIn: function(t, b, c, d) { 
 38                 return c * (t /= d) * t * t * t + b; 
 39             }, 
 40             strongEaseOut: function(t, b, c, d) { 
 41                 return c * (( t = t / d - 1 ) * t * t * t * t + 1) + b; 
 42             }, 
 43             sineaseIn: function(t, b, c, d) { 
 44                 return c * (t /= d) * t * t + b; 
 45             }, 
 46             sineaseOut: function(t, b, c, d) { 
 47                 return c * (( t = t / d - 1) * t * t + 1) + b; 
 48             } 
 49         }; 
 50  
 51         // 定义动画类 
 52         var Animate = function(dom) { 
 53             this.dom = dom; 
 54             this.startTime = 0; 
 55             this.startPos = 0; 
 56             this.endPos = 0; 
 57             this.propertyName = null; 
 58             this.easing = null; 
 59             this.duration = null; 
 60         } 
 61  
 62         // 动画启动 
 63         Animate.prototype.start = function(propertyName, endPos, duration, easing) { 
 64             this.propertyName = propertyName; 
 65             this.startTime = +new Date(); 
 66             this.startPos = this.dom.getBoundingClientRect()[propertyName]; 
 67             this.endPos = endPos; 
 68             this.duration = duration; 
 69             this.easing = tween[easing]; 
 70  
 71             var self = this; 
 72             var timeId = setInterval(function() { 
 73                 if (self.step() === false) { 
 74                     clearInterval(timeId); 
 75                 } 
 76             }, 1000/60) 
 77         } 
 78  
 79         Animate.prototype.step = function() { 
 80             var t = +new Date(); 
 81             if (t > this.startTime + this.duration) { 
 82                 this.update(this.endPos); 
 83                 return false; 
 84             } 
 85             var pos = this.easing(t - this.startTime,  
 86                 this.startPos, this.endPos - this.startPos, this.duration); 
 87             this.update(pos); 
 88         } 
 89  
 90         Animate.prototype.update = function( pos ) { 
 91             this.dom.style[ this.propertyName ] = pos + 'px'; 
 92         } 
 93  
 94  
 95         var ball = document.getElementById('ball'); 
 96         var pos = document.getElementById('pos'); 
 97         var moveBtn = document.getElementById('moveBtn'); 
 98         var cancelBtn = document.getElementById('cancelBtn'); 
 99  
100         // 使用命令模式实现事件和dom的解耦 
101         var MoveCommand = function(receiver, pos) { 
102             this.receiver = receiver; 
103             this.pos = pos; 
104             this.oldPos = null; 
105         } 
106  
107         MoveCommand.prototype.excute = function() { 
108             this.receiver.start('left', this.pos, 1000, 'strongEaseOut'); 
109             this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName]; 
110         } 
111  
112         MoveCommand.prototype.undo = function() { 
113             this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut'); 
114         } 
115  
116         var moveCommand; 
117  
118         moveBtn.onclick = function() { 
119             var animate = new Animate( ball ); 
120             moveCommand = new MoveCommand(animate, pos.value); 
121             moveCommand.excute(); 
122         } 
123  
124         cancelBtn.onclick = function() { 
125             console.log(moveCommand); 
126             moveCommand.undo(); 
127         } 
128     </script> 
129 </body> 
130 </html>


发布评论
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

设计模式------迭代器模式知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。