意图
intent
:将对象组合成树形结构以表示
“
部分
-
整体
”
的层次结构。
Composite
使得用户对单个对象和组合对象的使用具有一致性。
适用性: 1 ) 你想表示对象的部分- 整体层次结构。 2 )你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
Definition :
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Participants : The classes and/or objects participating in this pattern are:
Component (DrawingElement)
declares the interface for objects in the composition.
implements default behavior for the interface common to all classes, as appropriate.
declares an interface for accessing and managing its child components.
(optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate.
Leaf (PrimitiveElement)
represents leaf objects in the composition. A leaf has no children.
defines behavior for primitive objects in the composition.
Composite (CompositeElement)
defines behavior for components having children.
stores child components.
implements child-related operations in the Component interface.
Client (CompositeApp)
manipulates objects in the composition through the Component interface.
这个模式还是有点复杂的,是我到目前为止所学的最复杂的一个,因为我光看 UML 图还是不是很清楚。 Sigh ,看来俺还是太弱了。不过看了代码后就很清楚了。恩。
其中 Component 是一个抽象类, Composite 实现了 Component ,同时,它也保存了一个 Component 类型的数组成员。 Leaf 是 Component 的另一种实现,它没有一个数组,就相当于树叶,它不能再有子节点了。而 Composite 则相当于一个树枝,它可以有很多子节点。 Client 的话就是演示代码了。其它的也没什么了。要点是 Leaf 和 Composite 都来自同一个 Abstract class ,然后 Composite 拥有 Component 对象的一个数组。这样的话就会演化出一棵树来了。只要有一个 root 根节点,然后就一个节点一个节点的往上爬了,然后到 Leaf 树叶节点结束。恩。非常典型的一棵树啊。
不过现在好像也都把聚合也叫做组合了。怎么说呢?称呼是次要的,技术也是次要的,关键是做出来的东西!
Sample code in C#
This structural code demonstrates the Composite pattern which allows the creation of a tree structure in which individual nodes are accessed uniformly whether they are leaf nodes or branch (composite) nodes.
// Composite pattern -- Structural example
using System; using System.Collections; namespace DoFactory.GangOfFour.Composite.Structural { // MainApp test application class MainApp { static void Main() { // Create a tree structure 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); root.Add(new Leaf("Leaf C")); // Add and remove a leaf Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); // Recursively display tree root.Display(1); // Wait for user Console.Read(); } } // "Component" abstract class Component { protected string name; // Constructor 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); } // "Composite" class Composite : Component { private ArrayList children = new ArrayList(); // Constructor public Composite(string name) : base (name) { } public override void Add(Component component) { children.Add(component); } public override void Remove(Component component) { children.Remove(component); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); // Recursively display child nodes foreach (Component component in children) { component.Display(depth + 2); } } } // "Leaf" class Leaf : Component { // Constructor 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); } } }
Output -root
---Leaf A
---Leaf B
---Composite X
-----Leaf XA
-----Leaf XB
---Leaf C
This real-world code demonstrates the Composite pattern used in building a graphical tree structure made up of primitive nodes (lines, circles, etc) and composite nodes (groups of drawing elements that make up more complex elements).
// Composite pattern -- Real World example
using System; using System.Collections; namespace DoFactory.GangOfFour.Composite.RealWorld { // Mainapp test application class MainApp { static void Main() { // Create a tree structure CompositeElement root = new CompositeElement("Picture"); root.Add(new PrimitiveElement("Red Line")); root.Add(new PrimitiveElement("Blue Circle")); root.Add(new PrimitiveElement("Green Box")); CompositeElement comp = new CompositeElement("Two Circles"); comp.Add(new PrimitiveElement("Black Circle")); comp.Add(new PrimitiveElement("White Circle")); root.Add(comp); // Add and remove a PrimitiveElement PrimitiveElement pe = new PrimitiveElement("Yellow Line"); root.Add(pe); root.Remove(pe); // Recursively display nodes root.Display(1); // Wait for user Console.Read(); } } // "Component" Treenode abstract class DrawingElement { protected string name; // Constructor public DrawingElement(string name) { this .name = name; } public abstract void Add(DrawingElement d); public abstract void Remove(DrawingElement d); public abstract void Display(int indent); } // "Leaf" class PrimitiveElement : DrawingElement { // Constructor public PrimitiveElement(string name) : base (name) { } public override void Add(DrawingElement c) { Console.WriteLine( "Cannot add to a PrimitiveElement"); } public override void Remove(DrawingElement c) { Console.WriteLine( "Cannot remove from a PrimitiveElement"); } public override void Display(int indent) { Console.WriteLine( new String('-', indent) + " " + name); } } // "Composite" class CompositeElement : DrawingElement { private ArrayList elements = new ArrayList(); // Constructor public CompositeElement(string name) : base (name) { } public override void Add(DrawingElement d) { elements.Add(d); } public override void Remove(DrawingElement d) { elements.Remove(d); } public override void Display(int indent) { Console.WriteLine(new String('-', indent) + "+ " + name); // Display each child element on this node foreach (DrawingElement c in elements) { c.Display(indent + 2); } } } }
Output -+ Picture
--- Red Line
--- Blue Circle
--- Green Box
---+ Two Circles
----- Black Circle
----- White Circle
Reference: http://www.dofactory.com/Patterns/Patterns.aspx