组合模式(Composite)
如果将总公司当作一颗大树的根部的话,那么对于它的下属分公司其实是这棵树的分支,至于其他更小的职能部门,则是更小处的分支以至树叶。
组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的结构层次。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式结构图

组合模式成员分析
Component——组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件。
Composite——定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,例如增加Add和删除Remove。
Leaf——定义叶子节点行为,在组合中表示叶节点对象,叶节点没有子节点。叶子节点实现Add和Remove接口没有任何意义,因为它们没法再添加分支和树叶。实现它们可以消除叶节点和枝节点对象在抽象层次的区别,使它们具备一样的接口。
组合模式代码结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| 组合模式代码结构: 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); }
class Leaf : Component { public Leaf(string name) : base(name) { }
public override void Add(Component c) { throw new ArgumentException("叶节点无法增加分支"); } public override void Remove(Component c) { throw new ArgumentException("叶节点没有子节点,不能移除其子节点"); } public override void Display(int depth) { Console.WriteLine(new string('-',depth) + name); } }
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 Display(int depth) { Console.WriteLine(new string('-', depth) + name); foreach (Component component in children) { component.Display(depth + 2); } }
public override void Remove(Component c) { children.Remove(c); } }
客户端代码 Component root = new Composite("root"); root.Add(new Leaf("Leaf A")); Composite composite1 = new Composite("Composite X"); root.Add(composite1); composite1.Add(new Leaf("Leaf B")); Composite composite2 = new Composite("Composite Y"); composite1.Add(composite2); root.Display(1); Console.Read();
|
运行结果

组合模式总结
为了使整体和部分能够被一致对待,可以采用组合模式
有一个问题——为什么树叶Leaf中也有Add和Remove呢?
透明方式,也就是说在Component中声明所有用来管理子对象的方法,其中包括Add和Remove等。这样实现Component接口的所有子对象都具备了Add和Remove等。这样使得叶节点和根节点对于外界没有区别,它们具备一致的行为接口。问题是:实现叶节点的Add和Remove是没有意义的。
安全方式,也就是在Component不提供Add和Remove接口方法,那么子类的Leaf也就不需要实现它,而是在Composite声明所有用来管理子类的方法。这样就导致了不够透明,所有树叶类和树枝类将不具备相同的接口,客户端的调用需要做相应的判断,带来了不便。
何时使用组合模式?
当发现需求中是体现部分与整体层次的结构时,你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式。
使用组合模式有何好处?
- 组合模式定义包含了基本对象和组合对象的类层次结构。
- 基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何使用到基本对象的地方都可以使用组合对象了。
- 用户不用关心到底是处理一个叶节点还是处理一个组合部件,也就用不着定义组合而写一些选择判断语句了。
- 组合模式使得用户可以一致地使用组合结构和单个对象。
用到游戏开发中就是组件模式
组件模式是将独立的功能点做一个封装,便于增删和管理。
组件模式一般有两种,一种就是组合(就是经常拿来跟继承对比),另一种是属性扩展,就是将组件中的所有方法和属性,扩展到载体中。
例如,寻路组件,刚体组件等。
Unity中各种的Component就是组件,Unity就是组件的集合。