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 相关文章推荐
权威JavaScript 中的内存泄露模式
Aug 13 Javascript
需要做特殊处理的DOM元素属性的访问
Nov 05 Javascript
调试Javascript代码(浏览器F12及VS中debugger关键字)
Jan 25 Javascript
Firefox和IE兼容性问题及解决方法总结
Oct 08 Javascript
jQuery实现模拟marquee标签效果
Jul 14 Javascript
移动端H5开发 Turn.js实现很棒的翻书效果
Jun 20 Javascript
BootStrap数据表格实例代码
Sep 13 Javascript
Vue中this.$router.push参数获取方法
Feb 27 Javascript
node+koa2+mysql+bootstrap搭建一个前端论坛
May 06 Javascript
微信公众平台 发送模板消息(Java接口开发)
Apr 17 Javascript
vue移动端实现手机左右滑动入场动画
Jun 17 Javascript
vue使用swiper实现左右滑动切换图片
Oct 16 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
如何使用PHP计算上一个月的今天
2013/05/23 PHP
PHP三元运算的2种写法代码实例
2014/05/12 PHP
php有道翻译api调用方法实例
2014/12/22 PHP
php绘图之在图片上写中文和英文的方法
2015/01/24 PHP
php类的扩展和继承用法实例
2015/06/20 PHP
PHP验证码生成原理和实现
2016/01/24 PHP
php实现HTML实体编号与非ASCII字符串相互转换类实例
2016/11/02 PHP
不间断滚动JS打包类,基本可以实现所有的滚动效果,太强了
2007/12/08 Javascript
对于this和$(this)的个人理解
2013/09/08 Javascript
jquery查找父元素、子元素(个人经验总结)
2014/04/09 Javascript
使用jquery animate创建平滑滚动效果(可以是到顶部、到底部或指定地方)
2014/05/27 Javascript
使用forever管理nodejs应用教程
2014/06/03 NodeJs
使用jQuery在对象中缓存选择器的简单方法
2015/06/30 Javascript
jQuery简单实现仿京东商城的左侧菜单效果代码
2015/09/09 Javascript
jQuery插件Flexslider实现图片轮播、图文结合滑动切换效果
2020/04/16 Javascript
JavaScript计算器网页版实现代码分享
2016/07/15 Javascript
Node.js Sequelize如何实现数据库的读写分离
2016/10/23 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
node实现登录图片验证码的示例代码
2018/04/20 Javascript
微信小程序3种位置API的使用方法详解
2019/08/05 Javascript
python连接mysql数据库示例(做增删改操作)
2013/12/31 Python
Python中的对象,方法,类,实例,函数用法分析
2015/01/15 Python
python从入门到精通(DAY 1)
2015/12/20 Python
利用Python如何生成hash值示例详解
2017/12/20 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
Python代码使用 Pyftpdlib实现FTP服务器功能
2019/07/22 Python
python PIL和CV对 图片的读取,显示,裁剪,保存实现方法
2019/08/07 Python
Python装饰器用法与知识点小结
2020/03/09 Python
对Python 字典元素进行删除的方法
2020/07/31 Python
canvas如何绘制钟表的方法
2017/12/13 HTML / CSS
计算机应用专业学生的自我评价分享
2013/11/03 职场文书
玩具公司的创业计划书
2013/12/31 职场文书
校本教研工作制度
2014/01/22 职场文书
护理学应聘自荐书范文
2014/02/05 职场文书
教师年度考核个人总结
2015/02/12 职场文书
教你解决往mysql数据库中存入汉字报错的方法
2021/05/06 MySQL