《javascript设计模式》学习笔记七:Javascript面向对象程序设计组合模式详解


Posted in Javascript onApril 08, 2020

本文实例讲述了Javascript面向对象程序设计组合模式。分享给大家供大家参考,具体如下:

概述

关于组合模式的定义:组合模式(Composite Pattern)有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。来自百度百科:http://baike.baidu.com/view/3591789.htm

其实从面向对象之五之后,与javascript本身关系不是很大,更重要的是设计模式的一些概念,只要了解javascript面向对象的一般知识,掌握设计模式的含义,代码本身并不是很难。

这里简单说一下组合模式,其实组合模式就是将一系列相似或相近的对象组合在一个大的对象,由这个大对象提供一些常用的接口来对这些小对象进行操作,代码可重用,对外操作简单。例如对于一个form里的元素,不考虑页面设计的情况下,一般就剩下input了,对于这些input都有name和value的属性,因此可以将这些input元素作为form对象的成员组合起来,form对象提供对外的接口,便可以实现一些简单的操作,比如设置某个input的value,添加/删除某个input等等……

正文

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

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

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

示例:

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 select(列表)的操作(取值/赋值)
Mar 16 Javascript
js 剪切板应用clipboardData详细解析
Dec 17 Javascript
详解js闭包
Sep 02 Javascript
angular+bootstrap的双向数据绑定实例
Mar 03 Javascript
js实现随机点名小功能
Aug 17 Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
Feb 21 Javascript
Vue Prop属性功能与用法实例详解
Feb 23 Javascript
Vue使用.sync 实现父子组件的双向绑定数据问题
Apr 04 Javascript
layui use 定义js外部引用函数的方法
Sep 26 Javascript
详解Vue+elementUI build打包部署后字体图标丢失问题
Jul 13 Javascript
微信小程序实现电子签名功能
Jul 29 Javascript
Vue3为什么这么快
Sep 23 Javascript
vue开发移动端底部导航条功能
Apr 08 #Javascript
《javascript设计模式》学习笔记五:Javascript面向对象程序设计工厂模式实例分析
Apr 08 #Javascript
vue实现表单未编辑或未保存离开弹窗提示功能
Apr 08 #Javascript
JS快速实现简单计算器
Apr 08 #Javascript
javascript中contains是否包含功能实现代码(扩展字符、数组、dom)
Apr 07 #Javascript
vue-cli3单页构建大型项目方案
Apr 07 #Javascript
在Chrome DevTools中调试JavaScript的实现
Apr 07 #Javascript
You might like
PHP动态创建Web站点的方法
2011/08/14 PHP
laravel 解决路由除了根目录其他都404的问题
2019/10/18 PHP
简单的两种Extjs formpanel加载数据的方式
2013/11/09 Javascript
javascript获取form里的表单元素的示例代码
2014/02/14 Javascript
JavaScript设计模式之抽象工厂模式介绍
2014/12/28 Javascript
jQuery源码解读之removeClass()方法分析
2015/02/20 Javascript
JS实现动态移动层及拖动浮层关闭的方法
2015/04/30 Javascript
Bootstrap文件上传组件之bootstrap fileinput
2016/11/25 Javascript
JS常见疑难点分析之match,charAt,charCodeAt,map,search用法分析
2016/12/25 Javascript
canvas的神奇用法
2017/02/03 Javascript
axios学习教程全攻略
2017/03/26 Javascript
hammer.js实现图片手势放大效果
2017/08/29 Javascript
详解如何优雅地在React项目中使用Redux
2017/12/28 Javascript
JS精确判断数据类型代码实例
2019/12/18 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
2020/07/20 Javascript
[01:11:35]Liquid vs LGD 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python实现的简单抽奖系统实例
2015/05/22 Python
Python如何为图片添加水印
2016/11/25 Python
对Python 多线程统计所有csv文件的行数方法详解
2019/02/12 Python
Python利用pandas处理Excel数据的应用详解
2019/06/18 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
python飞机大战pygame游戏框架搭建操作详解
2019/12/17 Python
Python类及获取对象属性方法解析
2020/06/15 Python
python向xls写入数据(包括合并,边框,对齐,列宽)
2021/02/02 Python
HTML5中视频音频的使用详解
2017/07/07 HTML / CSS
英国最受信任的在线眼镜商之一:Fashion Eyewear
2019/10/31 全球购物
亚马逊加拿大网站:Amazon.ca
2020/01/06 全球购物
模特大赛策划方案
2014/05/28 职场文书
庆祝新中国成立65周年“向国旗敬礼”网上签名寄语
2014/09/27 职场文书
2014年企业员工工作总结
2014/12/09 职场文书
思想品德评语大全
2014/12/31 职场文书
北京英语导游词
2015/02/12 职场文书
五年级作文之学校的四季
2019/12/05 职场文书
导游词之安徽巢湖
2019/12/26 职场文书
python图像处理基本操作总结(PIL库、Matplotlib及Numpy)
2021/06/08 Python
Python实现查询剪贴板自动匹配信息的思路详解
2021/07/09 Python