什么是组合模式?
组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。
组合模式使得用户对单个对象和组合对象的使用具有一致性。
何时使用组合模式?
当需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,同意地使用组合结构中的所有对象时,就应该考虑用组合模式。
组合模式的组成
Component()
:组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。
声明一个接口用于访问和管理Component的子部件。
Leaf()
:在组合中表示叶节点对象,叶节点没有子节点。
Composite()
:定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add和删除Remove
组合模式具体实现
组合模式的结构
组合模式的实现:
Component():
1 abstract class Component 2 { 3 protected string name; 4 public Component(string name) 5 { 6 this.name = name; 7 } 8 public abstract void Add(Component c); 9 public abstract void Remove(Component c); 10 public abstract void Diaplay(int depth); 11 }
Leaf():
1 class Leaf : Component 2 { 3 public Leaf(string name) : base(name) 4 { } 5 6 public override void Add(Component c) 7 { 8 Console.WriteLine("Cannot add a leaf"); 9 } 10 11 public override void Diaplay(int depth) 12 { 13 Console.WriteLine(new String('-', depth) + name); 14 } 15 16 public override void Remove(Component c) 17 { 18 Console.WriteLine("Cannot remove from a leaf"); 19 } 20 }
Composite():
1 class Composite : Component 2 { 3 private List<Component> children = new List<Component>(); 4 public Composite(string name) : base(name) 5 { } 6 7 public override void Add(Component c) 8 { 9 children.Add(c); 10 } 11 12 public override void Diaplay(int depth) 13 { 14 //将 System.String 类的新实例初始化为由重复指定次数的指定 Unicode 字符指示的值 15 Console.WriteLine(new String('-', depth) + name); 16 foreach(Component component in children) 17 { 18 component.Diaplay(depth + 2); 19 } 20 } 21 22 public override void Remove(Component c) 23 { 24 children.Remove(c); 25 } 26 }
主函数调用:
1 static void Main(string[] args) 2 { 3 Composite root = new Composite("root"); 4 root.Add(new Leaf("Leaf A")); 5 root.Add(new Leaf("Leaf B")); 6 7 Composite comp = new Composite("Composite X"); 8 comp.Add(new Leaf("Leaf XA")); 9 comp.Add(new Leaf("Leaf XB")); 10 11 root.Add(comp); 12 13 Composite comp2 = new Composite("Composite XY"); 14 comp2.Add(new Leaf("Leaf XYA")); 15 comp2.Add(new Leaf("Leaf XYB")); 16 17 comp.Add(comp2); 18 19 root.Add(new Leaf("Leaf C")); 20 21 Leaf leaf = new Leaf("Leaf D"); 22 root.Add(leaf); 23 root.Remove(leaf); 24 25 root.Diaplay(1); 26 27 Console.Read(); 28 }
实现效果:
实例解析
为了深化理解,我们准备一个具体的实例来分析。
分析:
具体实现:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ConcreteCompany root = new ConcreteCompany("北京公司总部"); 6 root.Add(new HRDepartment("北京公司总部人力资源部")); 7 root.Add(new FinanceDepartment("北京公司总部财务部")); 8 9 ConcreteCompany com = new ConcreteCompany("上海分公司"); 10 com.Add(new HRDepartment("上海分公司人力资源部")); 11 com.Add(new FinanceDepartment("上海分公司财务部")); 12 13 root.Add(com); 14 15 ConcreteCompany com2 = new ConcreteCompany("南京办事处"); 16 com2.Add(new HRDepartment("南京办事处人力资源部")); 17 com2.Add(new FinanceDepartment("南京办事处财务部")); 18 19 com.Add(com2); 20 21 ConcreteCompany com3 = new ConcreteCompany("杭州办事处"); 22 com3.Add(new HRDepartment("杭州办事处人力资源部")); 23 com3.Add(new FinanceDepartment("杭州办事处财务部")); 24 com.Add(com3); 25 26 Console.WriteLine(" 结构图:"); 27 root.Diaplay(1); 28 29 Console.WriteLine(" 职责:"); 30 root.LineOfDuty(); 31 Console.Read(); 32 } 33 } 34 abstract class Company 35 { 36 protected string name; 37 public Company(string name) 38 { 39 this.name = name; 40 } 41 public abstract void Add(Company c); 42 public abstract void Remove(Company c); 43 public abstract void Diaplay(int depth); 44 public abstract void LineOfDuty(); 45 } 46 class ConcreteCompany : Company 47 { 48 private List<Company> children = new List<Company>(); 49 public ConcreteCompany(string name) : base(name) 50 { } 51 52 public override void Add(Company c) 53 { 54 children.Add(c); 55 } 56 57 public override void Diaplay(int depth) 58 { 59 Console.WriteLine(new String('-', depth) + name); 60 foreach(Company company in children) 61 { 62 company.Diaplay(depth + 2); 63 } 64 } 65 66 public override void LineOfDuty() 67 { 68 foreach(Company component in children) 69 { 70 component.LineOfDuty(); 71 } 72 } 73 74 public override void Remove(Company c) 75 { 76 children.Remove(c); 77 } 78 } 79 class HRDepartment : Company 80 { 81 public HRDepartment(string name) : base(name) 82 { 83 } 84 85 public override void Add(Company c) 86 { } 87 88 public override void Diaplay(int depth) 89 { 90 Console.WriteLine(new String('-', depth) + name); 91 } 92 93 public override void LineOfDuty() 94 { Console.WriteLine("{0} 员工招聘培训管理", name); } 95 96 public override void Remove(Company c) 97 { } 98 } 99 class FinanceDepartment : Company 100 { 101 public FinanceDepartment(string name) : base(name) 102 { } 103 104 public override void Add(Company c) 105 { } 106 107 public override void Diaplay(int depth) 108 { 109 Console.WriteLine(new String('-', depth) + name); 110 } 111 112 public override void LineOfDuty() 113 { 114 Console.WriteLine("{0} 公司财务收支管理", name); 115 } 116 117 public override void Remove(Company c) 118 { } 119 }
备注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。