The Composite design pattern composes objects into tree structures to represent part-whole hierarchies. This pattern lets clients treat individual objects and compositions of objects uniformly.
A visualization of the classes and objects participating in this pattern.
The classes and objects participating in this pattern include:
DrawingElement
)
PrimitiveElement
)
CompositeElement
)
CompositeApp
)
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.
using System;
using System.Collections.Generic;
namespace Composite.Structural
{
/// <summary>
/// Composite Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
// 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.ReadKey();
}
}
/// <summary>
/// The 'Component' abstract class
/// </summary>
public 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);
}
/// <summary>
/// The 'Composite' class
/// </summary>
public class Composite : Component
{
List<Component> children = new List<Component>();
// 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);
}
}
}
/// <summary>
/// The 'Leaf' class
/// </summary>
public 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);
}
}
}
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).
using System;
using System.Collections.Generic;
namespace Composite.RealWorld
{
/// <summary>
/// Composite Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
// 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"));
// Create a branch
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.ReadKey();
}
}
/// <summary>
/// The 'Component' Treenode
/// </summary>
public 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);
}
/// <summary>
/// The 'Leaf' class
/// </summary>
public 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);
}
}
/// <summary>
/// The 'Composite' class
/// </summary>
public class CompositeElement : DrawingElement
{
List<DrawingElement> elements = new List<DrawingElement>();
// 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 d in elements)
{
d.Display(indent + 2);
}
}
}
}
The .NET optimized code demonstrates the
same real-world situation as above but uses modern, built-in .NET features,
such as, generics, reflection, LINQ, lambda functions, etc.
You can find an example on our Singleton pattern page.
All other patterns (and much more) are available in our Dofactory .NET product.
Not only does Dofactory .NET cover the Gang of Four and Enterprise patterns, it also includes
pattern architectures, low-code, and RAD (Rapid Application Development) techniques.
Accelerate development to where you can write
entire solutions in just 33 days!.
This unique package will change your developer lifestyle.
Here's what is included: