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 - HTML的request类
Jul 15 Javascript
获取任意Html元素与body之间的偏移距离 offsetTop、offsetLeft (For:IE5+ FF1 )[
Dec 22 Javascript
JS返回iframe中frameBorder属性值的方法
Apr 01 Javascript
javascript实现一个数值加法函数
Jun 26 Javascript
JavaScript学习笔记(三):JavaScript也有入口Main函数
Sep 12 Javascript
JavaScript生成带有缩进的表格代码
Jun 15 Javascript
jQuery验证表单格式的使用方法
Jan 10 Javascript
JS实现匀加速与匀减速运动的方法示例
Sep 04 Javascript
js使用formData实现批量上传
Mar 27 Javascript
解析原来浏览器原生支持JS Base64编码解码
Aug 12 Javascript
微信小程序列表时间戳转换实现过程解析
Oct 12 Javascript
jquery实现购物车基本功能
Oct 25 jQuery
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
Zend Framework动作助手FlashMessenger用法详解
2016/03/05 PHP
PHP简单检测网址是否能够正常打开的方法
2016/09/04 PHP
laravel学习笔记之模型事件的几种用法示例
2017/08/15 PHP
laravel5 Eloquent 实现事务方式
2019/10/21 PHP
在laravel中实现ORM模型使用第二个数据库设置
2019/10/24 PHP
超级简单的图片防盗(HTML),好用
2007/04/08 Javascript
JS中三目运算符和if else的区别分析与示例
2014/11/21 Javascript
JS实现的新浪微博大厅文字内容滚动效果代码
2015/11/05 Javascript
JavaScript电子时钟倒计时第二款
2016/01/10 Javascript
animate 实现滑动切换效果【实例代码】
2016/05/05 Javascript
jquery+CSS3实现3D拖拽相册效果
2016/07/18 Javascript
wap手机端解决返回上一页的js实例
2016/12/08 Javascript
react中的ajax封装实例详解
2017/10/17 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
2018/02/04 Javascript
微信小程序仿美团城市选择
2018/06/06 Javascript
vuejs实现ready函数加载完之后执行某个函数的方法
2018/08/31 Javascript
Element Dropdown下拉菜单的使用方法
2020/07/26 Javascript
Python中的localtime()方法使用详解
2015/05/22 Python
Python基于select实现的socket服务器
2016/04/13 Python
Python基础知识点 初识Python.md
2019/05/14 Python
PyCharm专业最新版2019.1安装步骤(含激活码)
2019/10/09 Python
Python实现Word表格转成Excel表格的示例代码
2020/04/16 Python
Python私有属性私有方法应用实例解析
2020/09/15 Python
如何用 Python 制作一个迷宫游戏
2021/02/25 Python
Charles&Keith美国官方网站:新加坡快时尚鞋类和配饰零售商
2019/11/27 全球购物
经济学博士求职自荐信范文
2013/11/23 职场文书
捐赠仪式主持词
2014/03/19 职场文书
经贸专业毕业生求职信
2014/03/23 职场文书
环境整治工作方案
2014/05/18 职场文书
银行授权委托书范本
2014/10/04 职场文书
2014年教研员工作总结
2014/12/23 职场文书
怒海潜将观后感
2015/06/11 职场文书
2015暑假打工实践报告
2015/07/13 职场文书
煤矿施工安全协议书
2016/03/22 职场文书
为什么RedisCluster设计成16384个槽
2021/09/25 Redis
redis lua限流算法实现示例
2022/07/15 Redis