《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 相关文章推荐
基于prototype扩展的JavaScript常用函数库
Nov 30 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
Feb 05 Javascript
jQuery Uploadify 上传插件出现Http Error 302 错误的解决办法
Dec 12 Javascript
easyui取消表单实时验证,提交时统一验证的简单实例
Nov 07 Javascript
详解js的事件处理函数和动态创建html标记方法
Dec 16 Javascript
微信小程序 视图容器组件的详解及实例代码
Jan 19 Javascript
Vue获取DOM元素样式和样式更改示例
Mar 07 Javascript
详谈js使用in和hasOwnProperty获取对象属性的区别
Apr 25 Javascript
javascript 缓冲运动框架的实现
Sep 29 Javascript
Vue不能观察到数组length的变化
Jun 08 Javascript
JS中‘hello’与new String(‘hello’)引出的问题详解
Aug 14 Javascript
小程序接口的promise化的实现方法
Dec 11 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将数据导入到Foxmail
2006/10/09 PHP
php 实现进制转换(二进制、八进制、十六进制)互相转换实现代码
2010/10/22 PHP
ThinkPHP打水印及设置水印位置的方法
2016/10/14 PHP
PHP crc32()函数讲解
2019/02/14 PHP
jquery cookie插件代码类
2009/05/26 Javascript
js关闭父窗口时关闭子窗口
2013/04/01 Javascript
js使下拉列表框可编辑不止是选择
2013/12/12 Javascript
5种处理js跨域问题方法汇总
2014/12/04 Javascript
Javascript中拼接大量字符串的方法
2015/02/05 Javascript
javascript运动框架用法实例分析(实现放大与缩小效果)
2016/01/08 Javascript
JavaScript实战之菜单特效
2016/08/16 Javascript
轻松实现js弹框显示选项
2016/09/13 Javascript
jQuery实现一个简单的轮播图
2017/02/19 Javascript
vue2.0中goods选购栏滚动算法的实现代码
2017/05/17 Javascript
微信小程序开发之IOS和Android兼容的问题
2017/09/26 Javascript
Vue CLI3.0中使用jQuery和Bootstrap的方法
2019/02/28 jQuery
mpvue全局引入sass文件的方法步骤
2019/03/06 Javascript
微信小程序如何修改本地缓存key中单个数据的详解
2019/04/26 Javascript
微信小程序单选框自定义赋值
2020/05/26 Javascript
vue3中轻松实现switch功能组件的全过程
2021/01/07 Vue.js
Python实现Mysql数据库连接池实例详解
2017/04/11 Python
Python中sort和sorted函数代码解析
2018/01/25 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
使用python实现mqtt的发布和订阅
2019/05/05 Python
Python实现计算文件MD5和SHA1的方法示例
2019/06/11 Python
Python偏函数实现原理及应用
2020/11/20 Python
CSS实现鼠标滑过鼠标点击代码写法
2016/12/26 HTML / CSS
京东全球售:直邮香港,澳门,台湾,美国,澳大利亚等地区
2017/09/24 全球购物
Camper鞋西班牙官方网上商店:西班牙马略卡岛的鞋类品牌
2019/03/14 全球购物
中学教师岗位职责
2013/11/26 职场文书
法制宣传日活动总结
2014/04/29 职场文书
2014乡镇干部纪律作风整顿思想汇报
2014/09/13 职场文书
安全生产工作汇报
2014/10/28 职场文书
公司考勤管理制度
2015/08/04 职场文书
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang
《遗弃》开发商删推文要跑路?官方回应:还在开发
2022/04/03 其他游戏