- 本文已参与「新人创作礼」活动,一起开启掘金创作之路。
什么是组合模式
组合模式(Composite):将对象组合成树形结构以表示“ 部分 - 整体 ”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
什么时候使用组合模式
- 你要表示的对象是树状的
- 希望忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
组合模式结构
- 组件 (Component): 接口描述了树中简单项目和复杂项目所共有的操作。
- 叶节点 (Leaf): 是树的基本结构, 它不包含子项目。
- 容器 (Container):—是包含叶节点或其他容器等子项目的单位。 容器不知道其子项目所属的具体类, 它只通过通用的组件接口与其子项目交互。
类图(该图摘自深入设计模式一书)
代码实现
其实在我们平时生活中,比较常见的树结构像OA中的组织架构,像文件夹一层一层,都是非常经典的树结构。
如湖南总公司有两个部门为 人力资源部 和 IT研发部,总公司旗下广州分公司也有财务部和研发部,这样的情况是非常常见的,如果希望总公司的组织结构能复用到分公司应该如何处理呢。
- 通过了解概念我们声名组件抽象类,定义了树枝和树叶的公共属性和接口
public abstract class Component
{
public string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);// 用于操作节点的新增、删除操作
public abstract void Remove(Component c);
public abstract void Display(int dept);// 用于展示树结构,dept为深度
}
- 新增树枝即公司Company类,它具有Add 和 Remove方法用来新增或者删除叶子节点
// 公司类,相当于树枝
public class Company : Component
{
public List<Component> children = new List<Component>();
public Company(string name) : base(name)
{
this.name = name;
}
// 树枝应该存在Add 或者 Remove 来新增或者删除叶子节点
public override void Add(Component c)
{
children.Add(c);
}
//删除子节点
public override void Remove(Component c)
{
children.Remove(c);
}
// 这里使用递归思想,循环展示树结构
public override void Display(int dept)
{
Console.WriteLine(new string('*', dept) + name);
foreach (var item in children)
{
item.Display(dept + 2);
}
}
}
- 树形结构的Leaf即树的枝叶节点,是树的边缘不具备操作功能。
//具体部门即树形结构的Leaf 属于树结构的枝叶,不具备操作功能
public class HRDepartment : Component
{
public HRDepartment(string name) : base(name)
{
this.name = name;
}
public override void Add(Component c){ }
public override void Remove(Component c){ }
public override void Display(int dept)
{
Console.WriteLine(new string('*', dept) + name);
}
}
// 具体的IT研发部
public class ITDepartment : Component
{
public ITDepartment(string name) : base(name)
{
this.name = name;
}
public override void Add(Component c) { }
public override void Remove(Component c) { }
public override void Display(int dept)
{
Console.WriteLine(new string('*', dept) + name);
}
}
- 调用结果,符合树结构!
核心即使用递归循环调用展示树结构
总结
上文已详细叙述过如果你需要实现树状对象结构, 可以使用组合模式。使用组合模式可以更容易地往组合对象中加入新的构件,当然使用组合模式也会使设计更为复杂。
组合模式有透明式的实现 以及 安全式的实现,如上例子使用的是透明式。
- 透明模式,即所有操作方法都定义在Component里,好处就是叶子节点和树枝具有一致性,但是使得叶子节点本没有操作功能,也得空实现组件定义的操作方法,这是无意义的。
- 安全模,所谓安全模式就是将操作方法的定义放在Company类即树枝,那么叶子节点无需实现,但是这样树枝和叶子节点会产生不一致,需要做出判断才可使用。