JavaScript设计模式--组合模式

来源:互联网 发布:linux ntp服务安装 编辑:程序博客网 时间:2024/06/05 10:14

组合模式是操劳过度的JavaScript程序员的福音。。。。。。
因为,使用组合模式可以使用一条命令就(递归的)实现复杂的行为。
而这些行为是通过被委托给各个对象来实现的,就好像你只需要点亮树尖上的一盏灯,然后整个树上的灯就会依照你的代码依次被点亮。

组合对象的结构

组合模式的基本结构

组合对象中存在两种类型的对象:叶子对象和组合对象。叶子对象是组合模式中最基本的元素,也是所有操作最终被实现的地方。组合对象则由其他组合对象和叶子对象构成。

使用组合模式

使用组合模式的条件:
1、存在一批组织称某种层次体系的对象。
2、希望对这批对象全体或一部分实施某一个操作。
组合模式就是为了对一批对象进行操作的模式,它将对象组合成一颗树的样子,并且将命令从上向下进行传递。

栗子:表单验证

目标:创建一个有保存、恢复、验证功能的表单。
要求:表单中元素的内容和数目都是动态生成的,在编程过程中无法得知。

设计方案:
第一步:
将表单基本元素分解为组合对象和叶子对象
实现过程中,我们会要求顶层的对象根据代码递归的调用子对象上的方法。例如,如果我们调用topForm.save(),那么整个域的代码都会进行保存。但是实际上,真正执行了保存操作的是叶子结点(input/select/textarea)。

第二步:创建动态表单,实现save和validate

组合节点:

(如下代码中用到的接口模式代码见:http://blog.csdn.net/u014328357/article/details/70145306)

// 定义两个接口var Composite = new Interface('Composite',['add','remove','getChild']);var FormItem = new Interface('FormItem',['save']);var CompositeForm = function(id,method,action){    this.formComponents = [];    this.element = document.createElement('form');    this.element.id = id;    this.element.method = method || 'POST';    this.element.action = action || '#';};CompositeForm.prototype.add = function(child){    Interface.ensureImplements(child,Composite,FormItem);    this.formComponents.push(child);    this.element.appendChild(child.getElement());}CompositeForm.prototype.remove = function(child){    for(var i=0,len = this.formComponents.length;i<len;i++){         if(this.formComponents[i] === child){            this.formComponents.splice(i,1);            break;        }    }}

getchild/save/getElement方法

在对save方法的实现中我们很容易就发现了组合模式的工作方法:遍历子对象,并对它们调用同样的方法。

叶子结点:

var Field = function(id){    this.id = id;    this.element;}Field.prototype.add=function(){};Field.prototype.remove=function(){};Field.prototype.getChild=function(){};Field.prototype.save = function(){    setCookie(this.id,this.getValue());};Field.prototype.getElement = function(){    return this.element;};Field.prototype.getValue = function(){    throw new Error('Unsupported operation on the super class Field');};

这个对象将被作为‘父类’,由不同的叶子对象继承。下面给出inputField的代码:

var InputField = function(id,label){    Field.call(this,id);    this.input = document.createElement('input');    this.input.id = id;     this.label = document.createElement('label');    var labelTextNode = document.createTextNode(label);    this.label.appendChild(labelTextNode);     this.element = document.createElement('div');    this.element.ClassName = 'input-field';    this.element.appendChild(this.label);    this.element.appendChild(this.input);} extend(InputField,Field);InputField.prototype.getValue = function(){    return this.input.value;}

根据input的代码,我们可以仿照写出select和textarea的代码。

汇总
这部分体现了组合模式的优势所在,无论有多少个表单,对整个组合对象执行操作只需要调用一个函数即可。

var contactForm = new CompositeForm('contact-form','POST','contact.php');contactForm.add(new InputField('firstName','First Name'));contactForm.add(new InputField('lastName','Last Name'));contactForm.add(new InputField('address','Address'));contactForm.add(new InputField('city','City'));contactForm.add(new SelectField('state','State',stateArray));......addEvent(window,'unload',contactForm.save);//一个函数即可保存所有表单内容

在此基础上,我们可以为FormItem接口添加其他操作,或者向层次体系中添加新的类(也就是向组合模式的树上添加新的节点)。

组合模式的弊端:
有遍历操作,可能会影响性能。

0 0