javascript设计模式 ? 组合模式原理与应用实例分析


Posted in Javascript onApril 14, 2020

本文实例讲述了javascript设计模式 ? 组合模式原理与应用。分享给大家供大家参考,具体如下:

介绍:组合模式又叫部分整体模式,用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次

定义:组合多个对象形成树形结构以表示具有整体一部分关系的层次机构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以成为整体一部分模式。
它是一种对象结构型模式。

场景:我们对公司的人员架构进行一下打印,假设所有管理岗和开发岗的区别只有一个,是不是有下级员工。我们来实现下:

示例:

var LEADER = function(name,dept){
  this._name = name || '';  //姓名
  this._dept = dept || '';  //职位
  this._subordinates = [];  //下属
 
  this.add = function(employee){
    this._subordinates.push(employee);
  }
 
  this.remove = function(employee){
    this._subordinates.splice(this._subordinates.indexOf(employee),1);
  }
 
  this.getSubordinates = function(){
    return this._subordinates;
  }
  this.toString = function(){
    console.log('姓名:'+this._name+',职位:'+this._dept)
  }
}
var JAVARD = function(name,dept){
  this._name = name || '';  //姓名
  this._dept = dept || '';  //职位
 
  this.toString = function(){
    console.log('姓名:'+this._name+',职位:'+this._dept)
  }
}
 
var FERD = function(name,dept){
  this._name = name || '';  //姓名
  this._dept = dept || '';  //职位
  this.toString = function(){
    console.log('姓名:'+this._name+',职位:'+this._dept)
  }
}
 
function addData(){
  var CEO = new LEADER('spancer','CEO');
 
  var CTO = new LEADER('zijian','CTO');
 
  var MANAGER = new LEADER('jiang','LEADER');
 
  var JAVA_LEADER = new LEADER('fei','JAVA_LEADER');
  var FE_LEADER = new LEADER('risker','FE_LEADER');
 
  var wh = new FERD('wanghui','FE');
  var si = new FERD('si','FE');
  var amy = new FERD('amy','FE');
 
  var wei = new JAVARD('wei','JAVA');
  var guo = new JAVARD('guo','JAVA');
  var yuan = new JAVARD('yuan','JAVA');
 
  CEO.add(CTO);
 
  CTO.add(MANAGER);
 
  MANAGER.add(JAVA_LEADER);
  MANAGER.add(FE_LEADER);
 
  FE_LEADER.add(wh);
  FE_LEADER.add(si);
  FE_LEADER.add(amy);
 
  JAVA_LEADER.add(wei);
  JAVA_LEADER.add(guo);
  JAVA_LEADER.add(yuan);
  return CEO;
}
var eachEmployee = function(employee){
  for(var employ of employee.getSubordinates()){
    employ.toString();
    if(employ.getSubordinates && employ.getSubordinates().length > 0){
      eachEmployee(employ);
    }
  }
}
 
var CEO = addData();
CEO.toString();
eachEmployee(CEO);
// 姓名:spancer,职位:CEO
// 姓名:zijian,职位:CTO
// 姓名:jiang,职位:LEADER
// 姓名:fei,职位:JAVA_LEADER
// 姓名:wei,职位:JAVA
// 姓名:guo,职位:JAVA
// 姓名:yuan,职位:JAVA
// 姓名:risker,职位:FE_LEADER
// 姓名:wanghui,职位:FE
// 姓名:si,职位:FE
// 姓名:amy,职位:FE

这里我们简单写的这个demo,用来对公司组织架构进行遍历输出。因为rd和leader具体职能的不同,我们把技术和管理分为两大类。但是这样的设计存在很多问题:

* 可扩展性差,当一个新的职位产生,在对其归类时是新增一个还是放到已有类目下面都是一个问题。
* 当某一行为发生变化需要挨个修改leader类rd类,不符合开关原则。

接下来我们用组合模式实现下:

var Employee = function(name, dept){
  this._name = name || '';  //姓名
  this._dept = dept || '';  //职位
  this._subordinates = [];  //下属
 
  this.add = function(employee){
    this._subordinates.push(employee);
  }
 
  this.remove = function(employee){
    this._subordinates.splice(this._subordinates.indexOf(employee),1);
  }
 
  this.getSubordinates = function(){
    return this._subordinates;
  }
  this.toString = function(){
    console.log('姓名:'+this._name+',职位:'+this._dept)
  }
}
 
function addData(){
  var CEO = new Employee('spancer','CEO');
 
  var CTO = new Employee('zijian','CTO');
 
  var LEADER = new Employee('jiang','LEADER');
 
  var JAVA_LEADER = new Employee('fei','JAVA_LEADER');
  var FE_LEADER = new Employee('risker','FE_LEADER');
 
  var wh = new Employee('wanghui','FE');
  var si = new Employee('si','FE');
  var amy = new Employee('amy','FE');
 
  var wei = new Employee('wei','JAVA');
  var guo = new Employee('guo','JAVA');
  var yuan = new Employee('yuan','JAVA');
 
  CEO.add(CTO);
 
  CTO.add(LEADER);
 
  LEADER.add(JAVA_LEADER);
  LEADER.add(FE_LEADER);
 
  FE_LEADER.add(wh);
  FE_LEADER.add(si);
  FE_LEADER.add(amy);
 
  JAVA_LEADER.add(wei);
  JAVA_LEADER.add(guo);
  JAVA_LEADER.add(yuan);
  return CEO;
}
var eachEmployee = function(employee){
  for(var employ of employee.getSubordinates()){
    employ.toString();
    if(employ.getSubordinates().length > 0){
      eachEmployee(employ);
    }
  }
}
 
var CEO = addData();
CEO.toString();
eachEmployee(CEO);
// 姓名:spancer,职位:CEO
// 姓名:zijian,职位:CTO
// 姓名:jiang,职位:LEADER
// 姓名:fei,职位:JAVA_LEADER
// 姓名:wei,职位:JAVA
// 姓名:guo,职位:JAVA
// 姓名:yuan,职位:JAVA
// 姓名:risker,职位:FE_LEADER
// 姓名:wanghui,职位:FE
// 姓名:si,职位:FE
// 姓名:amy,职位:FE

大家可以对比下两段代码的差异,我们用一个Employee类来替换leader和rd类,其实这就是组合模式的关键:

定义一个抽象类,它既可以代表leader也可以代表rd,添加、打印时也基于Employee类,而无需知道这个人是什么角色。可以对其进行统一处理。

组合模式总结:

优点:
* 可以清楚的定义存在层次关系的复杂对象,让客户端开发过程中忽略层次的差异
* 全局修改时,只需修改一处位置

缺点:
* 无法对生成结果进行限制,不能像第一个例子一样,所有的rd都没有下级员工属性,也没有对应方法。所以在使用时要注意这些约束

适用场景;
* 在一个面向对象的语言开发系统中需要处理一个树形结构。
* 在具有整体和部分的结构中,希望忽略掉二者差异,使客户端一致对待。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

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

Javascript 相关文章推荐
tagName的使用,留一笔
Jun 26 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
Mar 28 Javascript
关于jQuery object and DOM element
Apr 15 Javascript
现如今最流行的JavaScript代码规范
Mar 08 Javascript
js验证IP及子网掩码的合法性有效性示例
Apr 30 Javascript
Jsonp post 跨域方案
Jul 06 Javascript
jQuery ajax全局函数处理session过期后的ajax跳转问题
Jun 03 Javascript
火狐和ie下获取javascript 获取event的方法(推荐)
Nov 26 Javascript
jquery 禁止鼠标右键并监听右键事件
Apr 27 jQuery
关于Stream和Buffer的相互转换详解
Jul 26 Javascript
webpack4与babel配合使es6代码可运行于低版本浏览器的方法
Oct 12 Javascript
小程序如何在不同设备上自适应生成海报的实现方法
Aug 20 Javascript
vue项目前端微信JSAPI与外部H5支付相关实现过程及常见问题
Apr 14 #Javascript
JavaScript代码压缩工具UglifyJS和Google Closure Compiler的基本用法
Apr 13 #Javascript
JS实现表单中点击小眼睛显示隐藏密码框中的密码
Apr 13 #Javascript
vue cli3适配所有端方案的实现
Apr 13 #Javascript
RxJS在TypeScript中的简单使用详解
Apr 13 #Javascript
JS错误处理与调试操作实例分析
Apr 13 #Javascript
JS正则表达式常见函数与用法小结
Apr 13 #Javascript
You might like
如何选购合适的收音机
2021/03/01 无线电
PHP学习之PHP运算符
2006/10/09 PHP
php获取url参数方法总结
2014/11/13 PHP
phpStudy配置多站点多域名和多端口的方法
2017/09/01 PHP
Referer原理与图片防盗链实现方法详解
2019/07/03 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
javascript中的作用域和上下文使用简要概述
2013/12/05 Javascript
最短的IE判断var ie=!-[1,]分析
2014/05/28 Javascript
jquery中页面Ajax方法$.load的功能使用介绍
2014/10/20 Javascript
js实现网页随机切换背景图片的方法
2014/11/01 Javascript
原生js页面滚动延迟加载图片
2015/12/20 Javascript
JavaScript基础知识及常用方法总结
2016/01/10 Javascript
jquery使用Cookie和JSON记录用户最近浏览历史
2016/04/19 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
2016/12/29 Javascript
Javascript中数组去重与拍平的方法示例
2017/02/03 Javascript
js图片上传的封装代码
2017/08/01 Javascript
angularJS的radio实现单项二选一的使用方法
2018/02/28 Javascript
vuex的使用和简易实现
2021/01/07 Vue.js
wxPython学习之主框架实例
2014/09/28 Python
Python的Flask框架中web表单的教程
2015/04/20 Python
python字典的常用方法总结
2019/07/31 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
2020/02/18 Python
Python日志logging模块功能与用法详解
2020/04/09 Python
CSS实现定位元素居中的方法
2015/06/23 HTML / CSS
物流专业大学应届生求职信
2013/11/03 职场文书
英文推荐信格式范文
2014/05/09 职场文书
医药销售自我评价200字
2014/09/11 职场文书
中学生逃课检讨书
2015/02/17 职场文书
自我工作评价范文
2015/03/06 职场文书
CSS3 制作的悬停缩放特效
2021/04/13 HTML / CSS
Python实现简单的猜单词
2021/06/15 Python
德劲DE1105机评
2022/04/05 无线电
浅析JavaScript中的变量提升
2022/06/01 Javascript