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 相关文章推荐
jQuery对象和Javascript对象之间转换的实例代码
Mar 20 Javascript
jCallout 轻松实现气泡提示功能
Sep 22 Javascript
node.js中的http.response.write方法使用说明
Dec 14 Javascript
JavaScript中的函数声明和函数表达式区别浅析
Mar 27 Javascript
js获取页面description的方法
May 21 Javascript
jQuery实现可以控制图片旋转角度效果(附demo源码下载)
Jan 27 Javascript
完美解决iview 的select下拉框选项错位的问题
Mar 02 Javascript
关于RxJS Subject的学习笔记
Dec 05 Javascript
新版小程序登录授权的方法
Dec 12 Javascript
详解Vue 全局变量,局部变量
Apr 17 Javascript
JS数组及对象遍历方法代码汇总
Jun 16 Javascript
JS如何生成动态列表
Sep 22 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
ThinkPHP的模版中调用session数据的方法
2014/07/01 PHP
yii实现创建验证码实例解析
2014/07/31 PHP
十个PHP高级应用技巧果断收藏
2015/09/25 PHP
PHP基于单例模式实现的mysql类
2016/01/09 PHP
在Mac OS上编译安装Nginx+PHP+MariaDB开发环境的教程
2016/02/23 PHP
javascript 匿名函数的理解(透彻版)
2010/01/28 Javascript
js 获取子节点函数 (兼容FF与IE)
2010/04/18 Javascript
GridView中获取被点击行中的DropDownList和TextBox中的值
2013/07/18 Javascript
Jquery动态替换div内容及动态展示的方法
2015/01/23 Javascript
Node.js的项目构建工具Grunt的安装与配置教程
2016/05/12 Javascript
解决vue 界面在苹果手机上滑动点击事件等卡顿问题
2018/11/27 Javascript
微信小程序:数据存储、传值、取值详解
2019/05/07 Javascript
vue+express+jwt持久化登录的方法
2019/06/14 Javascript
利用原生JS实现欢乐水果机小游戏
2020/04/23 Javascript
Vue中keep-alive的两种应用方式
2020/07/15 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
[09:13]2014DOTA2国际邀请赛 中国区预选赛coser表演
2014/05/23 DOTA
python3使用tkinter实现ui界面简单实例
2014/01/10 Python
Python中使用异常处理来判断运行的操作系统平台方法
2015/01/22 Python
使用python实现省市三级菜单效果
2016/01/20 Python
python开发环境PyScripter中文乱码问题解决方案
2016/09/11 Python
详谈Numpy中数组重塑、合并与拆分方法
2018/04/17 Python
Python常用爬虫代码总结方便查询
2019/02/25 Python
关于python字符串方法分类详解
2019/08/20 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
北美三大旅游网站之一:Travelocity
2017/08/12 全球购物
linux比较文件内容的命令是什么
2015/09/23 面试题
土木工程毕业生自荐信
2013/09/21 职场文书
销售自荐信
2013/10/22 职场文书
门卫工作岗位职责
2013/12/17 职场文书
中学生爱国演讲稿
2013/12/31 职场文书
2014年有孩子的离婚协议书范本
2014/10/08 职场文书
生产设备维护保养制度
2015/08/06 职场文书
九年级语文教学反思
2016/03/03 职场文书
解决Mysql的left join无效及使用的注意事项说明
2021/07/01 MySQL
openstack中的rpc远程调用的方法
2021/07/09 Python