设计模式中的组合模式在JavaScript程序构建中的使用


Posted in Javascript onMay 18, 2016

定义

组合,顾名思义是指用包含多个部件的对象创建单一实体。 这个单一实体将用作所有这些部件的访问点,虽然这大大简化了操作,但也可能具有相当的欺骗性,因为没有哪种隐性方式明确表明该组合包含多少部件。
组合模式的目标是解耦客户程序与复杂元素内部架构,使得客户程序对待所有子元素都一视同仁。

每个子节点都可以使复杂的存在,对于父节点来说,不需要知道子节点的复杂性或者实现子节点的复杂性,只需要关注子节点的特定方法,便可以使用子节点。简化了父和子之间的关系。

对于子节点来说也是一样的,过多的接口暴露有时候也是一种滥用,同时也减少了对外部的依赖。

示例
我们最好使用例证解说组合。 在下图中,您可以看到两种不同类型的对象: 容器和库是组合,图像是叶片。 组合可承载子项,但一般不会实施更多行为。 叶片包含绝大多数行为,但不能承载子项,至少在传统的组合示例中不可以。

设计模式中的组合模式在JavaScript程序构建中的使用

此示例创建图片库,将其作为组合模式示例。 只有三个层次: 专辑、库和图像。 专辑和库将作为组合,图像是叶片,如上面那张图所示。这是一种比组合本身需求更加明确的结构,但对于本示例而言,将这些层次仅限制为组合或叶片很有意义。 标准组合不会限制哪些结构层次可以具有叶片,也不会限制叶片数量。

要开始操作,应首先创建用于专辑和库的 GalleryComposite“类”。 请注意,我正在使用 jQuery 执行 DOM 操作以简化过程。

var GalleryComposite = function (heading, id) {
  this.children = [];

  this.element = $('<div id="' + id + '" class="composite-gallery"></div>')
  .append('<h2>' + heading + '</h2>');
}

GalleryComposite.prototype = {
  add: function (child) {
    this.children.push(child);
    this.element.append(child.getElement());
  },

  remove: function (child) {
    for (var node, i = 0; node = this.getChild(i); i++) {
      if (node == child) {
        this.children.splice(i, 1);
        this.element.detach(child.getElement());
        return true;
      }

      if (node.remove(child)) {
        return true;
      }
    }

    return false;
  },

  getChild: function (i) {
    return this.children[i];
  },

  hide: function () {
    for (var node, i = 0; node = this.getChild(i); i++) {
      node.hide();
    }

    this.element.hide(0);
  },

  show: function () {
    for (var node, i = 0; node = this.getChild(i); i++) {
      node.show();
    }

    this.element.show(0);
  },

  getElement: function () {
    return this.element;
  }
}

这个位置有点棘手,能否允许我再更多的解释一下? 我们同时使用 add, remove, 和getChild getChild 方法构建这一组合。 本示例不会实际使用 remove 和 getChild,但它们对于创建动态组合非常有用。 hide, show, 和getElement 方法则用来操纵 DOM。 该组合旨在作为库的 表示在页面上向用户展示。 该组合可通过 hide 和 show控制这些库元素。 如果在专辑上调用 hide,则整个专辑将消失,或者您也可以只在单一图像上调用它,这样只有该图像会消失。

现在,创建一个 GalleryImage类。 请注意,它使用的方法与 GalleryComposite完全相同。 换句话说,它们实现同一接口,不同的是该图像是叶片,因此不会实际对子项相关方法执行任何操作,就像不具有任何子项一样。 必须使用同一接口运行该组合,因为组合元素不知道自身添加的是另一个组合元素还是叶片,因此如果尝试在其子项上调用这些方法,则需要运行完全正常,没有任何错误。

var GalleryImage = function (src, id) {
  this.children = [];

  this.element = $('<img />')
  .attr('id', id)
  .attr('src', src);
}

GalleryImage.prototype = {
  // Due to this being a leaf, it doesn't use these methods,
  // but must implement them to count as implementing the
  // Composite interface
  add: function () { },

  remove: function () { },

  getChild: function () { },

  hide: function () {
    this.element.hide(0);
  },

  show: function () {
    this.element.show(0);
  },

  getElement: function () {
    return this.element;
  }
}

鉴于您已经构建了对象原型,您现已能够进行使用。 从下面您可以看到实际构建图像库的代码。

var container = new GalleryComposite('', 'allgalleries');
var gallery1 = new GalleryComposite('Gallery 1', 'gallery1');
var gallery2 = new GalleryComposite('Gallery 2', 'gallery2');
var image1 = new GalleryImage('image1.jpg', 'img1');
var image2 = new GalleryImage('image2.jpg', 'img2');
var image3 = new GalleryImage('image3.jpg', 'img3');
var image4 = new GalleryImage('image4.jpg', 'img4');

gallery1.add(image1);
gallery1.add(image2);

gallery2.add(image3);
gallery2.add(image4);

container.add(gallery1);
container.add(gallery2);

// Make sure to add the top container to the body,
// otherwise it'll never show up.
container.getElement().appendTo('body');
container.show();

组合模式之利:
简单的操作也能产生复杂的结果,只需对最顶层的对象执行操作,让每一个子对象自己传递这个操作即可。这对于那些再三执行的操作尤其有用。

在组合模式中,各个对象之间的耦合非常松散。只要它们实现了同样的接口那么改变它们的位置或互换它们只是举手之劳。着促进了代码的重用,也有利于代码重构。

每当对顶层组合对象执行一个操作时,实际上是在对整个结构进行深度优先的搜索以查找节点,而创建组合对象的程序员对这些细节一无所知。在这个层次体系中添加、删除和查找节点都非常容易。

组合模式之弊:
组合对象的易用性可能掩盖了它所支持的每一种操作的代价。由于组合对象调用的任何操作都会被传递到它的所有子对象如果这个层次体系很大的话,系统的性能将会受到影响。组合模式的正常运作需要用到某种形式的接口。

组合对象和节点类被用作HTML元素的包装工具时,组合对象必须遵守HTML的使用规则。例如,表格就很难转化为一个组合对象。

接口检查越严格,组合对象类也就越可靠。

Javascript 相关文章推荐
XRegExp 0.2: Now With Named Capture
Nov 30 Javascript
兼容多浏览器的字幕特效Marquee的通用js类
Jul 20 Javascript
asp.net下利用js实现返回上一页的实现方法小集
Nov 24 Javascript
当jQuery1.7遇上focus方法的问题
Jan 26 Javascript
JavaScript中通过提示框跳转页面的方法
Feb 14 Javascript
jQuery操作dom实现弹出页面遮罩层(web端和移动端阻止遮罩层的滑动)
Aug 25 Javascript
js 转json格式的字符串为对象或数组(前后台)的方法
Nov 02 Javascript
基于ajax与msmq技术的消息推送功能实现代码
Dec 26 Javascript
vue路由前进后退动画效果的实现代码
Dec 10 Javascript
Vue 实现复制功能,不需要任何结构内容直接复制方式
Nov 09 Javascript
JavaScript如何判断input数据类型
Feb 06 Javascript
vue2路由方式--嵌套路由实现方法分析
Mar 06 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
May 18 #Javascript
详解JavaScript设计模式开发中的桥接模式使用
May 18 #Javascript
jquery解析XML及获取XML节点名称的实现代码
May 18 #Javascript
Jquery跨域获得Json的简单实例
May 18 #Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
May 18 #Javascript
jQuery使用ajax跨域获取数据的简单实例
May 18 #Javascript
JQuery 的跨域方法推荐_可跨任何网站
May 18 #Javascript
You might like
PHP操作MongoDB时的整数问题及对策说明
2011/05/02 PHP
解析php中array_merge与array+array的区别
2013/06/21 PHP
浅谈PHP中的
2016/04/23 PHP
javascript 三种编解码方式
2010/02/01 Javascript
关于hashchangebroker和statehashable的补充文档
2011/08/08 Javascript
网站404页面3秒后跳到首页的实例代码
2013/08/16 Javascript
在Ubuntu上安装最新版本的Node.js
2014/07/14 Javascript
通过js为元素添加多项样式,浏览器全兼容写法
2014/08/30 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
jQuery中fadein与fadeout方法用法示例
2016/09/16 Javascript
AngularJS入门示例之Hello World详解
2017/01/04 Javascript
JS+HTML5实现上传图片预览效果完整实例【测试可用】
2017/04/20 Javascript
JavaScript实现form表单的多文件上传
2020/03/27 Javascript
w3c编程挑战_初级脚本算法实战篇
2017/06/23 Javascript
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
Vue 使用中的小技巧
2018/04/26 Javascript
IE8中jQuery.load()加载页面不显示的原因
2018/11/15 jQuery
Vue中el-form标签中的自定义el-select下拉框标签功能
2020/04/20 Javascript
python递归打印某个目录的内容(实例讲解)
2017/08/30 Python
基于Python函数的作用域规则和闭包(详解)
2017/11/29 Python
django将图片上传数据库后在前端显式的方法
2018/05/25 Python
Python 利用scrapy爬虫通过短短50行代码下载整站短视频
2018/10/29 Python
详解Python_shutil模块
2019/03/15 Python
解决python中导入win32com.client出错的问题
2019/07/26 Python
Python实现图像的垂直投影示例
2020/01/17 Python
Python面向对象中类(class)的简单理解与用法分析
2020/02/21 Python
AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码
2020/08/19 HTML / CSS
澳大利亚领先的运动鞋商店:Hype DC
2018/03/31 全球购物
毕业生就业意向书
2014/04/01 职场文书
学校师德承诺书
2014/05/23 职场文书
安全伴我行演讲稿
2014/09/04 职场文书
征用土地赔偿协议书
2014/09/26 职场文书
大学生村官工作总结2015
2015/04/09 职场文书
2016年端午节寄语
2015/12/04 职场文书
《中国机长》观后感:敬畏生命,敬畏职责
2019/11/12 职场文书