JavaScript命令模式原理与用法实例详解

本文实例讲述了JavaScript命令模式原理与用法。分享给大家供大家参考,具体如下:

第一,命令模式:
(1)用于消除调用者和接收者之间直接的耦合的模式,并且可以对(调用这个过程进行留痕操作)

(2)真的不要乱用这个模式,以为他使你简单调用写法变得非常的复杂和有些难以理解。

(3)你的业务出现了 (回退操作)(重做操作)的需求的时候你就要考虑使用这个模式了。
命令的原理:

一种情况为发出者直接作用于执行者,这样耦合度很高,另外一种情况为,在发出者和执行者之间增加一个用存储命令的命令访问库也即命令命令模式。

第二,现在我们通过一个需求来学习该模式
需求为:

1.有一个"添加流程的按钮"单击的时候 就会添加一个新的文本当做流程的描述

2.有"返回","重做" 2个按钮来完成相应的任务。
第三,界面为

<body>
<input type="text" id="flow">
<input type="button" value="添加新流程" onclick="API.addFlow()">
<br>
<input type="button" value="ctrl+z回退" onclick="API.ret()">
<input type="button" value="ctrl+z+x重做" onclick="API.again()">
<div id= "div01"></div>

<script src="Js/设计模式第三部分/命令模式/keymaster.min.js"></script>
<script src="Js/设计模式第三部分/命令模式/uuid.js"></script>
<script src="Js/设计模式第三部分/命令模式/(18)命令模式.js"></script>
</body>

效果为,

根据上述图我们逐步完成
步骤一,定义主应用程序----接收者

 function manager() {
        this.addFlow=function (id,value) {
            //1.得到目标节点
          var div=document.getElementById("div01");
          var newFlow=document.createElement("div");
          newFlow.setAttribute("id",id);
          newFlow.innerHTML=value;
          div.appendChild(newFlow);

        }
    }

步骤二,为对象(执行者)建立命令访问库 ---意思是可以通过extcute方法访问到addFlow方法

 manager.prototype.extcute=(function () {
      /*command 命令对象
      * */
      return function (command) {
        return this[command.method](command.id,command.value);
      }

    })();

步骤三,初始化主类

 var ma = new manager();//可以用该对象,调用其的东西
      //用于存储"调用对象命令的"集合
      var commands = new Array();
      //集合的游标--初始化在末尾
      var index = commands.length;

步骤四,客户端----发出者

 var API=function () {
   this.addFlow=function () {
     //把调用封装起来
     var command={
       method:"addFlow",
       id:new UUID().createUUID(),//产生id的插件
       value:document.getElementById("flow").value
     };
     //把调用对象保存起来,用于回退和重做作用
     commands.push(command);
     //重新定位游标---赋值记录
     index = commands.length;
     //调用
     ma.extcute(command);
   };
   /**
    * 用于返回的方法
    */
   this.ret=function () {
     if(index-1<0){
       alert("已经到了最后一步了...");
     }else {
       var all=document.getElementById("div01").childNodes;
       document.getElementById("div01").removeChild(all[all.length-1]);
       index=index-1;
     }
   };
   /**
    * 用于重做的方法
    */
   this.again=function () {
     if(index>=commands.length){
       alert("已经到了最前面一步了,不能进行重做...");
     }else {
       var command=commands[index];//获取当前的命令位置
       ma.extcute(command);
       index=index+1;
     }
   }
 }

步骤五,实例化客户端

API=new API();//实例化

这样html中的事件就可以起作用了。

在这里我们使用插件来让其功能支持自定义的键盘事件,插件名称为:keymaster.js

首先,如html中一样引入文件,

然后值调用key添加自定义的键盘事件

//添加支持ctrl+z--返回
key("ctrl+z",function () {

  API.ret();
});
//重做---
key("ctrl+shift+x",function () {
  API.again();

})

为此我们可以使用键盘的指定组合实现和鼠标点击一样的效果。

这里需要说明一下客户端的API中的id值,也是通过插件来动态生成的------插件名称为:uuid.js。这里附上源码

/*

uuid.js - Version 0.2
JavaScript Class to create a UUID like identifier

Copyright (C) 2006-2008, Erik Giberti (AF-Design), All rights reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

The latest version of this file can be downloaded from
http://www.af-design.com/resources/javascript_uuid.php

HISTORY:
6/5/06   - Initial Release
5/22/08 - Updated code to run faster, removed randrange(min,max) in favor of
     a simpler rand(max) function. Reduced overhead by using getTime()
     method of date class (suggestion by James Hall).

KNOWN ISSUES:
- Still no way to get MAC address in JavaScript
- Research into other versions of UUID show promising possibilities
 (more research needed)
- Documentation needs improvement

*/

// On creation of a UUID object, set it's initial value
function UUID(){
  this.id = this.createUUID();
}

// When asked what this Object is, lie and return it's value
UUID.prototype.valueOf = function(){ return this.id; }
UUID.prototype.toString = function(){ return this.id; }

//
// INSTANCE SPECIFIC METHODS
//

UUID.prototype.createUUID = function(){
  //
  // Loose interpretation of the specification DCE 1.1: Remote Procedure Call
  // described at http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagtcjh_37
  // since JavaScript doesn't allow access to internal systems, the last 48 bits
  // of the node section is made up using a series of random numbers (6 octets long).
  //
  var dg = new Date(1582, 10, 15, 0, 0, 0, 0);
  var dc = new Date();
  var t = dc.getTime() - dg.getTime();
  var h = '-';
  var tl = UUID.getIntegerBits(t,0,31);
  var tm = UUID.getIntegerBits(t,32,47);
  var thv = UUID.getIntegerBits(t,48,59) + '1'; // version 1, security version is 2
  var csar = UUID.getIntegerBits(UUID.rand(4095),0,7);
  var csl = UUID.getIntegerBits(UUID.rand(4095),0,7);

  // since detection of anything about the machine/browser is far to buggy,
  // include some more random numbers here
  // if NIC or an IP can be obtained reliably, that should be put in
  // here instead.
  var n = UUID.getIntegerBits(UUID.rand(8191),0,7) +
      UUID.getIntegerBits(UUID.rand(8191),8,15) +
      UUID.getIntegerBits(UUID.rand(8191),0,7) +
      UUID.getIntegerBits(UUID.rand(8191),8,15) +
      UUID.getIntegerBits(UUID.rand(8191),0,15); // this last number is two octets long
  return tl + h + tm + h + thv + h + csar + csl + h + n;
}

//
// GENERAL METHODS (Not instance specific)
//

// Pull out only certain bits from a very large integer, used to get the time
// code information for the first part of a UUID. Will return zero's if there
// aren't enough bits to shift where it needs to.
UUID.getIntegerBits = function(val,start,end){
  var base16 = UUID.returnBase(val,16);
  var quadArray = new Array();
  var quadString = '';
  var i = 0;
  for(i=0;i<base16.length;i++){
    quadArray.push(base16.substring(i,i+1));
  }
  for(i=Math.floor(start/4);i<=Math.floor(end/4);i++){
    if(!quadArray[i] || quadArray[i] == '') quadString += '0';
    else quadString += quadArray[i];
  }
  return quadString;
}

// Numeric Base Conversion algorithm from irt.org
// In base 16: 0=0, 5=5, 10=A, 15=F
UUID.returnBase = function(number, base){
  //
  // Copyright 1996-2006 irt.org, All Rights Reserved.
  //
  // Downloaded from: http://www.irt.org/script/146.htm
  // modified to work in this class by Erik Giberti
  var convert = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  if (number < base) var output = convert[number];
  else {
    var MSD = '' + Math.floor(number / base);
    var LSD = number - MSD*base;
    if (MSD >= base) var output = this.returnBase(MSD,base) + convert[LSD];
    else var output = convert[MSD] + convert[LSD];
  }
  return output;
}

// pick a random number within a range of numbers
// int b rand(int a); where 0 <= b <= a
UUID.rand = function(max){
  return Math.floor(Math.random() * max);
}

// end of UUID class file

感兴趣的朋友可以使用在线HTML/CSS/JavaScript前端代码调试运行工具:http://tools.jb51.net/code/WebCodeRun测试上述代码运行效果。

更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • JavaScript观察者模式原理与用法实例详解

    本文实例讲述了JavaScript观察者模式原理与用法.分享给大家供大家参考,具体如下: 观察者模式 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己. * 它分为2个角色:(1)观察者 (2)被观察者 * 观察者模式的目的:对程序的内在变化进行观察,当其有变化的时候,你可以得知,并且可以做出相应的反应. 现在我们通过一个需求来学习该模

  • JavaScript设计模式之缓存代理模式原理与简单用法示例

    本文实例讲述了JavaScript设计模式之缓存代理模式原理与简单用法.分享给大家供大家参考,具体如下: 一.原理: 缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参数跟之前的一致,则可以直接返回前面存储的运算结果,提供效率以及节省开销. 二.实例: var mult = function(){ console.log('开始计算乘机'); var a = 1; for(var i = 0, l = arguments.length;i < l;i++){ a =

  • JavaScript设计模式之代理模式简单实例教程

    本文实例讲述了JavaScript设计模式之代理模式.分享给大家供大家参考,具体如下: 一.代理模式概念 代理,顾名思义就是帮助别人做事,GoF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问.代理模式使得代理对象控制具体对象的引用.代理几乎可以是任何对象:文件,资源,内存中的对象,或者是一些难以复制的东西. 解释:房屋中介,可以代理帮助卖家把房子卖给买家,这中间卖家说要卖的价钱就可以了,买家也可以提出自己要买的房型,中介可以帮忙处理中间环节.最后达成

  • JavaScript的设计模式经典之代理模式

     一.代理模式概念 说明:顾名思义就是用一个类来代替另一个类来执行方法功能,这个模式跟装饰模式有点相似,不一样的是,代理模式是代替客户初始化被代理对象类,而装饰模式采用接口或初装饰者参数引用的方式来执行的. 解释:房屋中介,可以代理帮助卖家把房子卖给买家,这中间卖家说要卖的价钱就可以了,买家也可以提出自己要买的房型,中介可以帮忙处理中间环节.最后达成买卖.中介可以同时代理很多房屋买卖,并且可以代理租房事宜. 二.代理模式的作用和注意事项 模式作用: 1.远程代理(一个对象将不同空间的对象进行局部

  • JavaScript代理模式原理与用法实例详解

    本文实例讲述了JavaScript代理模式原理与用法.分享给大家供大家参考,具体如下: 代理模式的定义,代理是一个对象(proxy)用它来控制目标对象的访问.为此他要是先与目标对象相同的接口,但是他不同于装饰者模式,它对目标对象不进行任何修改,它的目的在于延缓"复杂"对象的初始化时间.这样可以在用到这个目标对象的时候再初始化他(对于单例来讲更是重要). 代理模式有两种分类: (1)普通代理 (2)惰性代理 具体看下面的例子 第一,普通代理模式 步骤一,接口检验文件的引用 //定义一个静

  • 轻松掌握JavaScript代理模式

    在面向对象设计中,有一个单一职责原则,指就一个类(对象.函数)而言,应该仅有一个引起它变化的原因.如果一个对象承担了过多的职责,就意味着它将变得巨大,引起它变化的原因就多,它把这些职责耦合到了一起,这种耦合会导致程序难于维护和重构. 这时候,我们可以把该对象(本体)的其中一部分职责分离出来给一些第三方对象去做,本体只管自己的一些核心职责,这些第三方对象就称作代理.代理对象可以作为对象(也叫"真正的主体")的保护者,让真正的主体对象做尽量少的工作.在代理设计模式中,一个对象充当了另一个对

  • JavaScript设计模式之代理模式介绍

    代理模式说明 说明:顾名思义就是用一个类来代替另一个类来执行方法功能,这个模式跟装饰模式有点相似,不一样的是,代理模式是代替客户初始化被代理对象类,而装饰模式采用接口或初装饰者参数引用的方式来执行的. 在动态面向对象语言里,代理模式即起到控制修饰被代理类的作用,也对被代理类起到了充分的隐藏保护作用:被代理类只到我们需要时,才被间接初始化调用: 场景描述: 很常见到的就是租房子的例子,房客要租房子,房东要把房子租出去,但是房客跟房东都没怎么有空找房子或在家等着有人看房子,就一同去找房屋中介.房东把

  • js设计模式之代理模式及订阅发布模式实例详解

    本文实例讲述了js设计模式之代理模式及订阅发布模式.分享给大家供大家参考,具体如下: 为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文章的第二篇文章,第一篇:. 1,代理模式,只是学习了虚拟代理以及缓存代理,具体案例 1)虚拟代理 //业务代码 var myImage = (function() { var imgNode = document.

  • JavaScript设计模式之代理模式详解

    代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子.但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处.在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为. /** * pre:代理模式 * 小明追求A,B是A的好朋友,小明比较腼腆,不好意思直接将花交给A, * 于是小明将花交给B,再由B交给A. */ //----------- 示例1 --------- // 不使用代理

  • JavaScript装饰者模式原理与用法实例详解

    本文实例讲述了JavaScript装饰者模式原理与用法.分享给大家供大家参考,具体如下: 这里我们通过需求逐渐引出装饰者模式. 下面是一个关于几代汽车的不同逐渐体现装饰者模式的. 首先,我们先引入一个接口文件----目的为检验实现类是否完全实现接口中的方法,代码如下, //定义一个静态方法来实现接口与实现类的直接检验 //静态方法不要写出Interface.prototype ,因为这是写到接口的原型链上的 //我们要把静态的函数直接写到类层次上 //定义一个接口类 var Interface=

  • JavaScript享元模式原理与用法实例详解

    本文实例讲述了JavaScript享元模式原理与用法.分享给大家供大家参考,具体如下: 通过两个例子的对比来凸显享元模式的特点:享元模式是一个为了提高性能(空间复杂度)的设计模式,享元模式可以避免大量非常相似类的开销. 第一实例,没有使用享元模式,计算所花费的时间和空间使用程度. 要求为:有一个城市要进行汽车的登记 (1)汽车类 /** * 制造商 * 型号 * 拥有者 * 车牌号码 * 最近一次登记日期 */ var Car = function(make,model,year,owner,t

随机推荐