组合对象,包括部件对象和叶对象.叶对象相当于最小粒度,不可再划分;而部件对象也是组合对象,是由叶对象组合而成.小的组合对象再经过不断组合,就成为一个大的组合对象;大的组合对象再次组装,就是一个整体.代码通过组合模式组合起来之后,具体执行请求时,是从上而下沿着树形结构进行传递的,一直传递到不可划分的叶子节点对象.

栗子:
创建一个表单.要求点提交按钮,可以保存和验证各项的值.这个表单的元素有多少项并不知道,也不知道具体是什么内容,是注册表单验证还是登陆表单验证?根据用户的需求而异,也就是实现一个动态表单.这时,组合模式就派上用场了,如下图:
图片描述

将动态form看成一个整体,然后根据粒度划分出最小叶子节点.根据上图和我们dom节点类型,我们可以将input,select,textarea三种类型的节点看做叶子对象.划分出最小叶子对象后,就可以根据实际场景,划分出由叶子对象组合成的部件对象,部件对象再经过随意无限次组合,可以成为最终的满足某一需求的form表单,非常灵活.

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>组合模式</title>
<head>
<body>
</body>
</html>
<script type="text/javascript">
var CompositeForm = function(id) {
  this.formComponents = [];
  this.formElement = document.createElement('form');
  this.formElement.id = id;
  this.formElement.onsubmit = function() {
    return false;
  }
}

CompositeForm.prototype.add = function(child) {
  this.formComponents.push(child);
}

CompositeForm.prototype.loadElements = function() {
  for(var i=0; i<this.formComponents.length; i++) {
    this.formElement.appendChild(this.formComponents[i].divElement);
  }
  var submitButton = document.createElement('input');
  submitButton.id = 'sub';
  submitButton.type = 'submit';
  this.formElement.appendChild(submitButton);
}

CompositeForm.prototype.save = function() {
  for(var i=0; i<this.formComponents.length; i++) {
    this.formComponents[i].save();
  }
}

var InputField = function(label, id, type) {
  //创建input节点
  this.input = document.createElement('input');
  this.input.id = id;
  this.input.type = type;
  //创建文本节点
  this.label = document.createElement('label');
  var labelTextNode = document.createTextNode(label);
  this.label.appendChild(labelTextNode);
  //创建div节点
  this.divElement = document.createElement('div');
  this.divElement.className = 'input-field';
  this.divElement.appendChild(this.label);
  this.divElement.appendChild(this.input);
}

InputField.prototype.save = function() {
  var value = this.input.value;
  sessionStorage.setItem(this.input.id, value);
  console.log(sessionStorage.getItem(this.input.id));
}

var form = new CompositeForm('myform');
//开始组合
form.add(new InputField('用户名', 'userName', 'text'));
form.add(new InputField('密码', 'password', 'password'));
form.add(new InputField('邮箱', 'email', 'text'));

//装填所有节点
form.loadElements();

//append到body
document.body.appendChild(form.formElement);

//试验一下
document.getElementById('sub').onclick = function() {
  form.save();
}
</script>

小被子
839 声望10 粉丝