欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

javascript设计模式 – 组合模式原理与应用实例分析

程序员文章站 2022-06-17 14:50:10
本文实例讲述了javascript设计模式 – 组合模式原理与应用。分享给大家供大家参考,具体如下:介绍:组合模式又叫部分整体模式,用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对...

本文实例讲述了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.jb51.net/code/htmljsrun测试上述代码运行效果。