JavaScript 组件之旅(一):分析和设计
作者:太伯 来源:Alipay UED 发布时间:2009-09-21 10:52:00
毫无疑问,JavaScript 是一种非常灵活的脚本语言,有时候它像一只难以驯服的野马——你受益于它的灵活性的同时,也要时刻提防它变得失去控制;另一方面,由于 JavaScript 通常会和宿主环境(比如浏览器)紧密结合,因此缺乏功能强大而简单易用的开发工具。在这样的环境中,开发组件或框架成为一项具有挑战的工作。
这次,我们将以一个简易的 JavaScript 组件开发为契机,逐步展开组件的分析、设计、实现、构建和测试等任务,探讨组件开发过程涉及的方方面面。这些探讨将分 4 篇陆续张贴出来(链接将在张贴后更新):
现在,假设我们要从头开始设计并实现一个队列管理组件,先让我们来认识一下队列:
Queue
图片来自 Wikipedia.
队列是一个“先进先出”(FIFO) 的数据结构,只能向它的尾巴追加项,项从头部取出使用,这个规则将应用到我们所探讨的组件中去。对于队列,相信学过 C 或是数据结构课程的同学已有所了解,如果你已经把它还给了老师,请使用搜索引擎简单了解一下队列的知识。
这个队列管理组件具体要实现的功能是:它是个任务管理器,按高、中、低优先级维护着三个任务队列,客户(使用者)可以在任何时候把想要执行的任务添加到某个队列,可以指定任务运行的上下文,并传给它必要的数据。客户也可以随时运行这个队列,队列里的任务按照指定的依赖关系以合理的方式依次运行。
为了不至于使组件过于简单而缺乏实用性,我们特意给它添加了一些“糖”:分优先级、传入上下文和数据、处理依赖关系。如果把上面这段理解为需求的话,那么首先,我们要从中提取出最重要的关键词,它们直接决定了这个组件应该如何设计:
队列
优先级
依赖关系
然后,我们从中提炼出涉及的对象:
任务管理器 (TaskManager): 从目前需求来看,它只需要一个实例。
队列 (Queue): 每个优先级对应一个队列,由
TaskManager
管理这三个Queue
实例。任务 (Task): 描述添加的任务,放在相应优先级的
Queue
里面。依赖 (Dependency): 描述单一的依赖,即
Task1
依赖Task2
, 显然某个Task
可能具有多个依赖。
它的对象模型可以大概表示如下:
设计初期的对象图
注意到 Dependency
实际上并没有做什么事,而 Queue
的两个方法可以分别交给 TaskManager
& Task
来负责。一个方法到底由哪个对象负责,是很容易引起争论的话题,不在我们的讨论范围内。这次,我们的重点是,采用 JavaScript 实现这个组件,结合 JavaScript 独特的语言特性,我们设想实现上述四个对象:
TaskManager
直接通过对象 (Object) 实现。在 JavaScript 的世界,对象可以作为天然的静态类来使用——你可以直接在“类”ClassObject
里面定义属性方法property
,并以静态类的方式来引用CassObject.property
.Queue
以数组 (Array) 的形式体现出来,Task
则是数组中存放的每一项。对Queue
进行操作必然要在其 prototype 中定义一些实例方法,由于每个 Queue 实例都是原生的数组,为了减少对Array.prototype
的侵入,我们可以考虑将这些方法定义到Task.prototype
上——将职责转移到任务上。
将三个Queue
数组集结在一起,形成一个“大数组”以表示三个不同优先级的队列,这个大数组可以作为TaskManager
的属性。任务的核心是一个 function, 本来可以直接用 function 来表示一个任务,但考虑到它具有自身独特的属性(优先级、依赖等等),而且是最经常 * 作的对象,以后可能还会进行扩展,所以我们决定单独将其定义成对象。
依赖直接以数组的形式作为
Task
的一个属性存在——Task
将依赖的其他多个Task
标识符放在这个数组中,不再单独定义这个对象。
分析下来,局势逐渐明朗——我们需要将四个对象简化成两个:TaskManager
& Task
, 另外两个对象用原生的数组来实现:
简化后的对象模型
又注意到这里多次以数组来实现,而编码过程中必然涉及到数组的遍历、查找等操作,JavaScript 1.6 已经为我们实现了这些数组操作。为了充分利用数组内置的原生方法,又能在较老的浏览器中运行,我们使用了 Eric 的代码。这样,我们可以直接使用诸如 forEach
/indexOf
等方法,更关注组件的功能实现,而且在现代浏览器中获得较好的性能。
~~~~~~~~~~~~~ 八卦分割线 ~~~~~~~~~~~~~
嗯,在严肃地分析了组件设计之后,就要踏上快乐的编码实现之旅了。别急,TaskManager
似乎俗气了一点:不足以表达具有优先级、依赖管理的任务队列,而且用它做命名空间有跟其他代码冲突的可能性。好吧,这个组件就叫 Smart Queue
吧,响亮而又独特.^^
分析设计好了,名字也有了,欲知具体实现过程,且听下回分解。


猜你喜欢
- 1. 在控制台输入以下命令,检查Jupyter notebook的安装目录jupyter notebook --generate-confi
- 1.安装插件,在非虚拟环境conda install nb_condaconda install ipykernel2、安装ipykerne
- 实体有五种预定义的XML实体,HTML编码者应该熟悉。XML文档中的字符&、<、>、"和'被分别表示为
- 1.简要概述为什么要开通MySQL这个学习板块呢?因为这是一名数据分析师必要的一项技能。分析数据什么最重要?当然是数据,既然如此!在数据呈现
- 在Vista IIS 7 中用 vs2005 调试 Web 项目核心是要解决以下几个问题:1、Vista 自身在安全性方面的User Acc
- 一、Python不同版本的类Python2.2之前是没有共同的祖先的,之后引入Object类,它是所有类的共同祖先类ObjectPython
- 本文实例讲述了Python中super关键字用法。分享给大家供大家参考。具体分析如下:在Python类的方法(method)中,要调用父类的
- 本文总结了组件Bootstrap Select2在一些实际项目中的用法,分享给大家,有需要的朋友可以借鉴一下,少走些弯路,具体内容如下效果图
- JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于ECMAScript的一个子集。 JSON
- 笔者remove TensorFlow总共四次。 reinstall anaconda 三次。安装技巧可以根据这个博主的文章进行安装。htt
- 本文介绍的是python中pandas.DataFrame对行与列求和及添加新行与列的相关资料,下面话不多说,来看看详细的介绍吧。方法如下:
- 密码保护是注册过程中的关键环节,尤其是对帐户安全级别比较高的网站,尤其在账号被盗或者涉及安全登录等问题的情况下,密码保护问题作为用户身份识别
- 介绍godep是解决包依赖的管理工具,目前最主流的一种,原理是扫描记录版本控制的信息,并在go命令前加壳来做到依赖管理godep 建议在 g
- pycharm报错提示:无法加载文件\venv\Scripts\activate.ps1,因为在此系统上禁止运行脚本在pycharm终端出现
- code:f = open('yesterday','r',encoding='utf-8'
- 关于最近要在python下做可视化界面的设计,想到之前用QtDesigner来画界面很是方便,当时画完之后都要手动在终端输入 pyuic5
- 本文实例讲述了Python3.5运算符操作。分享给大家供大家参考,具体如下:1、运算符的分类2、算术运算符示例代码:#!/usr/bin/e
- 1.必需的参数:必须参数须以正确的顺序传入函数,调用的数量必须和声明时的一样def f(name,age):print('I am
- 一、读取Excel文件使用pandas的read_excel()方法,可通过文件路径直接读取。注意到,在一个excel文件中有多个sheet
- 该脚本是为了结合之前的编写的脚本,来实现数据的比对模块,实现数据的自动化!由于数据格式是定死的,该代码只做参考,有什么问题可以私信我!CSV