乐趣区

关于前端:设计模式之组合模式

在日常生活中存在很多 局部和整体 的关系,他们都具备一致性,然而有各有个的行为,比方大学中的部门与学院、总公司的部门与分公司、学习用品中的书与书包、生活用品中的衣服与衣柜,以及厨房中的锅碗瓢盆等。

然而在我的项目开发中也存在雷同的情理,当咱们做人员管理系统的时候,公司上面是部门,每个部门上面可能会有分组,组之后才是人员,那么按照此例的话,就造成了一个树状的构造,以总公司为根基,一层一层的向下递归。对这些简略的对象来与复合对象的解决,用组合模式模式实现起来可能会更加的失当和不便。

什么是组合模式

组合模式:组合模式,将对象组合成树形构造以示意“局部 - 整体”的层次结构。用户对单个对象和组合对象的应用具备一致性。—— 节选自百度百科

其实在文章结尾曾经说了比拟详尽了,组合模式通过创建对象的组的树形构造,把对象组合成树状构造以示意整体及局部的构建关系。组合模式一句树状构造把对象进行组合,以用来示意局部以及整体之间的档次关系,这种类型的设计模式隶属于结构型设计模式,组合模式使用户对单个对象和组合对象的拜访都具备一致性。能够让客户端用同一种形式解决个别对象以及对象组合。当咱们的业务属于树状构造的时候,就能够适当的思考应用组合模式。

组合模式优缺点

组合模式中蕴含一个容器,然而这个容器是由多个包含容器在内的子容器所形成的,组合模式与其子类都领有雷同的办法。然而,组合模式自身并不实现其中具体的细节的一些工作,而是把这些申请递归的传给本人的子类型,最终实现后获取到最终想要的后果。

长处

  1. 组合模式是得客户端代码能够统一的解决单个对象和组合对象,并不需要关怀本人解决的是单个对象还是组合对象,大大的简化了客户端的代码
  2. 组合模式能够更容易的在组合类中加如新的对象,客户端不会因为退出了新的对象而更改源代码,从何满足开闭准则
  3. 应用组合模式时能够利用多态和递归的机制更加不便的应用简单树构建

毛病

  1. 客户端须要花更多的工夫理清类与类之间的档次关系,增大了客户端的复杂程度
  2. 不容易限度容器中的组成部分
  3. 不太可能用继承的形式减少构件的新性能

示例

笔者在翻阅材料的时候,发现组合模式又分成两种,别离是通明模式和平安模式。

组合模式的次要角色如下:

  1. 组件:接口形容了树中简略我的项目和简单我的项目所共有的操作。
  2. 叶节点:是树的根本构造,它不蕴含子项目。个别状况下,叶节点最终会实现大部分的理论工作,认为他们无奈将工作指派给其余局部。
  3. 容器:蕴含叶节点或其余容器等子项目的代为。容器领导其子我的项目所属的具体类,它只通过通用的组件接口与其子项目交互。
  4. 客户端:通过组件接口与所有我的项目交互,因而客户端以雷同形式与树状构造中的简略或简单我的项目交互。

通明模式

通明模式是把组合应用的办法放到抽象类中,不论叶子对象还是容器都有雷同的构造,这样做的益处就是叶子节点对与外界是没有任何区别的,他们具备完全一致的行为接口。然而因为叶对象自身不存在增加和删除性能,所以实现它是没有意义的。

类图如下所示:

代码示例:

abstract class Component {

  protected name:string;

  constructor(name:string){this.name = name;}

  //  减少一个叶子构件或树枝构件
  public abstract add(component:Component):void;

  //  删除一个叶子构件或树枝构件
  public abstract remove(component:Component):void;

  //  获取分支下的所有叶子构件和树枝构件
  public abstract display(depth:number):void;

}

class Composite extends Component {private componentArrayList:Component[] = []

  constructor(name:string){super(name);
  }

  public add(component:Component): void {this.componentArrayList.push(component);
  }

  public remove(component:Component): void {const {componentArrayList} = this;
    this.componentArrayList = componentArrayList.filter((el:Component) => component === el);
  }

  public display(depth:number):void {
    //  输入树形构造
    for(let i = 0; i < depth; i++) {console.log("------")
    }
    console.log(this.name);
    const {componentArrayList} = this;
    //  遍历下一级
    for (let i = 0,item:Component ;item = componentArrayList[i++];) {item.display(depth + 1);
    }
  }
}

class Leaf extends Component {constructor(name:string){super(name);
  }

  public add(component:Component): void {throw new Error("Unsupported request");
  }

  public remove(component:Component): void {throw new Error("Unsupported request");
  }

  //  输入树形构造的叶子节点
  public display(depth:number): void {for(let i = 0; i < depth; i++) {console.log('-');
    }
    console.log(this.name);
  }

}

const compositeOne = new Composite("CompositeOne");
const leafOne = new Leaf("CompositeOne-01");
compositeOne.add(leafOne);
compositeOne.add(new Leaf("CompositeOne-02"));
compositeOne.add(new Leaf("CompositeOne-03"));
compositeOne.display(1);

平安模式

平安模式是把树枝节点和树叶节点彻底离开,树枝节点独自又有用来组合的办法,这种办法比拟平安。然而因为不够通明,所以树叶节点和树枝节点将具备不同的接口,客户端的调用须要做相应的判断,带来了很大的不便。

类图如下所示:

代码示例:

abstract class Component {
  protected name:string;

  constructor(name:string){this.name = name;}

  public abstract display(depth:number):void;
};

class Composite extends Component {private componentArrayList:Component[] = [];

  constructor(name:string){super(name);
  }

  public add(component:Component): void {this.componentArrayList.push(component);
  }

  public remove(component:Component): void {const {componentArrayList} = this;
    this.componentArrayList = componentArrayList.filter((el:Component) => component === el);
  }

  public display(depth:number):void {
    //  输入树形构造
    for(let i = 0; i < depth; i++) {console.log("------")
    }
    console.log(this.name);
    const {componentArrayList} = this;
    //  遍历下一级
    for (let i = 0,item:Component ;item = componentArrayList[i++];) {item.display(depth + 1);
    }
  }

};

class Leaf extends Component {constructor(name:string){super(name);
  }

  public display(depth:number):void {
    // 输入树形构造的叶子节点
    for(let i=0; i<depth; i++) {console.log('-');
    }
    console.log(this.name);
  }

}

const compositeOne = new Composite("CompositeOne");
const leafOne = new Leaf("CompositeOne-01");
compositeOne.add(leafOne);
compositeOne.add(new Leaf("CompositeOne-02"));
compositeOne.add(new Leaf("CompositeOne-03"));
compositeOne.display(1);

大节

通过上述两种办法运行后果均是雷同的,却别在于外部实现的而已,一种是叶节点与树枝节点具备统一的行为接口但有空实现的通明模式,另一种是树枝节点独自领有用来组合的办法但调用不便的平安模式。为什么说它调用不便呢,因为咱们如果通过递归遍历树时,这时须要判断以后节点是叶子节点还是树枝节点,客户端就须要相应的判断。

总结

文章中剖析了组合模式的构造和特点(组合模式用于组合多个对象造成树形构造以示意具备局部 - 整体关系地层次结构。蕴含形象构件类,叶子构件类,容器构件类),综上所述在业务中须要示意一个对象整体与局部层次结构的场合的时候能够应用组合模式,当对用户暗藏组合对象与单个对象的不同,用户能够用对立的组合构造的对象的时候同样也能够应用组合模式。

退出移动版