1.定义
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
Component抽象构件角色:定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性。
Leaf叶子构件:叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
Composite树枝构件:树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
2.通用代码
1 namespace ConsoleApplication1 2 { 3 /// <summary> 4 /// 抽象构件 5 /// </summary> 6 public abstract class Component 7 { 8 //抽象方法 9 public abstract void DoSomeThing(); 10 } 11 12 /// <summary> 13 /// 树枝构件 14 /// </summary> 15 public class Composite : Component 16 { 17 private List<Component> _componentArrayList = new List<Component>(); 18 19 public void Add(Component c) 20 { 21 _componentArrayList.Add(c); 22 } 23 24 public void Remove(Component c) 25 { 26 _componentArrayList.Remove(c); 27 } 28 29 public List<Component> GetChildren() 30 { 31 return _componentArrayList; 32 } 33 } 34 35 /// <summary> 36 /// 枝叶构件 37 /// </summary> 38 public class Leaf : Component 39 { } 40 41 public class Client 42 { 43 public static void Main(string[] args) 44 { 45 Composite root = new Composite(); 46 47 Composite branch = new Composite(); 48 49 Leaf leaf = new Leaf(); 50 51 root.Add(branch); 52 53 branch.Add(leaf); 54 55 Console.ReadKey(); 56 57 } 58 59 private static void Display(Composite root) 60 { 61 foreach (var item in root.GetChildren()) 62 { 63 if (item is Leaf) 64 { 65 item.DoSomeThing(); 66 } 67 else 68 { 69 Display(item as Composite); 70 } 71 } 72 } 73 } 74 75 }
3.组合模式的缺点
组合模式有一个非常明显的缺点,看到我们在场景类中的定义,我们直接使用了树叶和树枝的具体实现类。这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。
4.使用场景
- 维护和展示部分-整体的场景,如树形菜单、文件和文件夹很容易。
- 从一个整体中能够独立出部分模块或功能的场景。
5.模式的扩展
- 透明的组合模式
组合模式有两种不同的实现:透明模式和安全模式。我们上面讲的是安全模式,那么透明模式是怎样的呢?透明模式的通用类图如下所示:
透明模式就是把用来组合使用的方法放到抽象类中,比如Add、Remove方法等。
1 namespace ConsoleApplication1 2 { 3 /// <summary> 4 /// 抽象构件 5 /// </summary> 6 public abstract class Component 7 { 8 private List<Component> _componentArrayList = new List<Component>(); 9 10 //抽象方法 11 public abstract void DoSomeThing(); 12 13 public abstract void Add(Component c) 14 { 15 _componentArrayList.Add(c); 16 } 17 18 public abstract void Remove(Component c) 19 { 20 _componentArrayList.Remove(c); 21 } 22 23 public abstract List<Component> GetChildren() 24 { 25 return _componentArrayList; 26 } 27 } 28 29 /// <summary> 30 /// 树枝构件 31 /// </summary> 32 public class Composite : Component 33 { 34 } 35 36 /// <summary> 37 /// 枝叶构件 38 /// </summary> 39 public class Leaf : Component 40 { 41 public override void Add(Component c) 42 { 43 throw new NotSupportedException(); 44 } 45 46 public override void Remove(Component c) 47 { 48 throw new NotSupportedException(); 49 } 50 51 public override List<Component> GetChildren() 52 { 53 throw new NotSupportedException(); 54 } 55 } 56 57 public class Client 58 { 59 public static void Main(string[] args) 60 { 61 Composite root = new Composite(); 62 63 Composite branch = new Composite(); 64 65 Leaf leaf = new Leaf(); 66 67 root.Add(branch); 68 69 branch.Add(leaf); 70 71 Console.ReadKey(); 72 73 } 74 75 private static void Display(Component root) 76 { 77 foreach (var item in root.GetChildren()) 78 { 79 if (item is Leaf) 80 { 81 item.DoSomeThing(); 82 } 83 else 84 { 85 Display(item); 86 } 87 } 88 } 89 } 90 91 }
- 从下向上遍历
在Component抽象类中添加Parent属性,当调用Add()方法时,设置Parent的值。