The composite design pattern is used to compose objects into a tree structure. So each element can hold a list of sub elements. Optional it may have a link to the parent object within the tree.
Within the following example I want to create a generic base class to implement the behavior of a tree node. This base class can be used for any object to create a tree structure.
At first we define the interface for the tree node.
public interface ITreeNode<T> { T AddChild(ITreeNode<T> child); void RemoveChild(ITreeNode<T> child); List<ITreeNode<T>> Children { get; } }
Next we implement the tree node object.
public class TreeNode<T> : ITreeNode<T> { private List<ITreeNode<T>> _children = new List<ITreeNode<T>>(); public List<ITreeNode<T>> Children { get { return _children; } } public T AddChild(ITreeNode<T> child) { _children.Add(child); return (T)child; } public void RemoveChild(ITreeNode<T> child) { _children.Remove(child); } }
Now let’s say you want to create a tree of visual elements. To keep it simple our visual element is a shape which has a name property only. By using the generic tree node you can simply create a shape tree node.
public class Shape : TreeNode<Shape> { public Shape(string name) { Name = name; } public string Name { get; set; } }
Finally we will create a console application to test our nice shape object. Within this application we create a complex shape containing a tree structure of sub shapes. And we create a recursive executed method to show our visual tree.
static void Main(string[] args) { Shape root = new Shape("Drawing"); root.AddChild(new Shape("Circle")); Shape rectangle = root.AddChild(new Shape("Rectangle")); root.AddChild(new Shape("Line")); rectangle.AddChild(new Shape("Dotted Line")); rectangle.AddChild(new Shape("Triangle")); Display(root); Console.ReadKey(); } private static void Display(Shape rootShape) { Display(rootShape, 1); } private static void Display(Shape shape, int level) { if (level > 1) { Console.Write(new string(' ', (level - 2) * 2)); Console.Write("> "); } Console.WriteLine(shape.Name); foreach (Shape child in shape.Children) { Display(child, level + 1); } }