组合模式
概述
将对象组合成树形结构以表示‘部分’和‘整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
主要是用来处理树形结构数据,因为其应用场景的特殊性,导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。
对业务场景的一种数据结构和算法的抽象。其中,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。
结构图

代码实现
构建树并展示
抽象构件
/// <summary> /// 抽象构件 /// </summary> public abstract class Component { protected 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 depth); }
枝叶构建
/// <summary> /// 枝叶构建 /// </summary> public class Composite : Component { private List<Component> children = new List<Component>(); public Composite(string name) : base(name) { } public override void Add(Component c) { children.Add(c); } public override void Remove(Component c) { children.Remove(c); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); foreach (Component component in children) { component.Display(depth + 2); } } }
树叶构件
/// <summary> /// 树叶构件 /// </summary> public class Leaf : Component { public Leaf(string name) : base(name) { } public override void Add(Component c) { Console.WriteLine("Cannot add to a leaf"); } public override void Remove(Component c) { Console.WriteLine("Cannot remove from a leaf"); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); } }
客户端
class Program { static void Main(string[] args) { Composite root = new Composite("root"); root.Add(new Leaf("Leaf A")); root.Add(new Leaf("Leaf B")); Composite comp = new Composite("Composite X"); comp.Add(new Leaf("Leaf XA")); comp.Add(new Leaf("Leaf XB")); root.Add(comp); Composite comp2 = new Composite("Composite XY"); comp2.Add(new Leaf("Leaf XYA")); comp2.Add(new Leaf("Leaf XYB")); comp.Add(comp2); root.Add(new Leaf("Leaf C")); Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); root.Display(1); Console.Read(); } }
运行结果

构建公司组织架构并计算全公司薪酬
员工和部门抽象类
//员工和部门抽象类 public abstract class HumanResource { protected long id; protected double salary; public HumanResource(long id) { this.id = id; } public long GetId() { return id; } public abstract double CalculateSalary(); }
枝叶构建
//部门 public class Department : HumanResource { List<HumanResource> subNodes = new List<HumanResource>(); public Department(long id) : base(id) { this.id = id; } public void AddSubNode(HumanResource humanResource) { subNodes.Add(humanResource); } //计算出部门薪资 public override double CalculateSalary() { double totalSalary = 0; foreach (var item in subNodes) { totalSalary += item.CalculateSalary(); } return totalSalary; } }
树叶构建
//员工 public class Employee : HumanResource { public Employee(long id, double salary) : base(id) { this.salary = salary; } //返回员工薪资 public override double CalculateSalary() { return salary; } }
客户端
static void Main(string[] args) { Department root = new Department(1); root.AddSubNode(new Employee(11, 123.4)); root.AddSubNode(new Employee(12, 123.5)); root.AddSubNode(new Employee(13, 123.5)); root.AddSubNode(new Employee(14, 123.5)); root.AddSubNode(new Func<Department>(() => { Department root_sub = new Department(15); root_sub.AddSubNode(new Employee(151, 123)); root_sub.AddSubNode(new Employee(152, 123)); root_sub.AddSubNode(new Employee(153, 123)); return root_sub; })()); root.AddSubNode(new Func<Department>(() => { Department root_sub = new Department(16); root_sub.AddSubNode(new Employee(161, 123)); root_sub.AddSubNode(new Employee(162, 123)); root_sub.AddSubNode(new Employee(163, 123)); return root_sub; })()); //计算出所有值 Console.WriteLine(root.CalculateSalary()); Console.Read(); }
运行结果

优势
高层模块调用简单。
节点自由增加。
在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
使用场景
当表示对象的部分-整体层次结构(树形结构)
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
缺陷
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
设计较复杂,客户端需要花更多时间理清类之间的层次关系
不容易限制容器中的构件
不容易用继承的方法来增加构件的新功能;

浙公网安备 33010602011771号