在JavaScript中理解组合模式

栏目: JavaScript · 发布时间: 6年前

内容简介:组合模式就是用小的子对象来构建更大的对象, 将对象组合成树形结构, 以表示 “部分-整体” 的层次结构.位于底层最小的对象, 我们在这里称为叶对象, 由叶对象组成的组合对象我们称为分支对象, 位于最顶层的根对象在这里我们也称为分支对象. 不过它们只是结构上呈现出父子关系.组合模式最大的好处可以一致性地对待分支对象和叶对象, 这也就要求了它们有着相同的接口.

组合模式就是用小的子对象来构建更大的对象, 将对象组合成树形结构, 以表示 “部分-整体” 的层次结构.

位于底层最小的对象, 我们在这里称为叶对象, 由叶对象组成的组合对象我们称为分支对象, 位于最顶层的根对象在这里我们也称为分支对象. 不过它们只是结构上呈现出父子关系.

组合模式最大的好处可以一致性地对待分支对象和叶对象, 这也就要求了它们有着相同的接口. 在JavaScript中理解策略模式 中, 我们对员工进行考核, 划分了甲乙丙三个等级. 现在, 公司决定结合等级以资鼓励.

以下所有代码参见compositeMode.

开销的占比

现有考核人员:

考核项目\考核人 等级 月薪
person_1 6k
person_2 9k
person_3 4k
person_4 5k
person_5 6k
person_6 5k
person_7 6k
person_8 4k
person_9 8k
const persons = [
  { scale: '甲', salary: 6000, company: 'JavaScript' },
  { scale: '乙', salary: 9000, company: 'JavaScript' },
  { scale: '乙', salary: 4000, company: 'JavaScript' },
  { scale: '乙', salary: 5000, company: 'JavaScript' },
  { scale: '丙', salary: 6000, company: 'JavaScript' },
  { scale: '丙', salary: 5000, company: 'JavaScript' },
  { scale: '丙', salary: 6000, company: 'JavaScript' },
  { scale: '丙', salary: 4000, company: 'JavaScript' },
  { scale: '丙', salary: 9000, company: 'JavaScript' },
  { scale: '甲', salary: 6000, company: 'JavaScript' },
]
复制代码

等级与月薪相关, 分别为3倍月薪、2倍月薪、1倍月薪.

等级
月薪倍率 3 2 1
const scaleMap = {
  '甲': 3,
  '乙': 2,
  '丙': 1
}
复制代码

到底需要拿出多少钱奖励呢? 甲乙丙三组人分别占比多少呢? 针对这样的需求, 我们尝试着用组合模式计算一下.

叶对象与分支对象

上面也提到了, 组合模式中有两类对象. 一个是分支对象, 一个是叶对象. 分支对象是叶对象的集合, 保存着叶对象的引用, 可以操作叶对象(比如添加, 执行). 而叶对象只要暴露接口即可. 现在我们从简单的开始, 造一个生产叶对象的函数.

const leaf = params => {
  return {
    ...params,
    expense() {
      return scaleMap[params.scale] * params.salary
    }
  }
}
复制代码

分支对象就稍微麻烦些了, 因为需要管理叶对象.

const branch = params => {
  return {
    ...params,
    members: [],
    add(item) {
      this.members.push(item)
    },
    expense() {
      return this.members.reduce((sum, item) => {
        return sum + item.expense()
      }, 0)
    }
  }
}
复制代码

expense() 的方法不论是在分支对象还是叶对象上, 或者说不清楚是分支对象还是叶对象, 我们都可以得到相应的结果. 在分支对象里, 保存着叶对象的引用, 我们可以对叶对象进行任何操作.

从JSON数据到树形结构

组合模式就是这么简单, 剩下的就是如何 JSON 数据转换成层次分明的结构了.

const convertData = array => {
  const branchList = [];
  const branchObjs = [];
  array.forEach(item => {
    let leafObj = leaf(item);
    if (!branchList.includes(item.scale)) {
      let params = {
        scale: item.scale
      }
      let branchObj = branch(params)
      branchObjs.push(branchObj)
      branchList.push(item.scale)
    }
    branchObjs.filter(obj => obj.scale == item.scale)[0].add(leafObj);
  })
  return branchObjs;
}
console.log('branchObjs', convertData(persons))
const scaleA = convertData(persons)[0]
const scaleB = convertData(persons)[1]
const scaleC = convertData(persons)[2]
console.log('甲', scaleA.expense())
console.log('乙', scaleB.expense())
console.log('丙', scaleC.expense())
复制代码

最终结果展示

在JavaScript中理解组合模式

如果我们想知道公司的总支出, 也可以把 scaleA, scaleB, scaleC 组合在一起作为公司的一子集.

const company = branch();
company.add(scaleA);
company.add(scaleB);
company.add(scaleC);
company.expense()
复制代码
在JavaScript中理解组合模式

不难发现, 我们可以随意组装对象而不会影响到其它节点, 任何一个集合或个体都能够单独运行. 我们也可以根据需要去组合更复杂的结构. 但是, 如果通过组合模式创建了太多的对象, 那么这些对象可能会让系统负担不起.

小结

  1. 组合模式对象形式上至少有两种, 分支对象和叶对象.

  2. 分支对象和叶对象拥有相同的接口, 且对一组叶对象操作具有同步一致性.

  3. 组合模式是 HAS-A (聚合)关系, 不是 IS-A.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

简约至上

简约至上

[英] Giles Colborne / 李松峰、秦绪文 / 人民邮电出版社 / 2011-1-1 / 35.00

追求简单易用是人类的本性,无论是互联网产品。还是移动应用。亦或其他交互式设计,简单易用始终都是赢得用户的关键。同时,简单易用的程度也与产品寿命的长短密切相关。在《简约至上:交互式设计四策略》中,作者Giles托20多年交互式设计的探索与实践。提出了合理删除、分层组织、适时隐藏和巧妙转移这四个达成简约至上的终极策略,讲述了为什么应该站在主流用户一边,以及如何从他们的真实需求和期望出发,简化设计,提升......一起来看看 《简约至上》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具