Objective ๐ฏ
Provide a way to compose objects into tree structures, also known as part-whole hierarchy, allowing the client to treat/work with each object of the structure individually.
Notes ๐
โข Composite pattern makes sense just in scenarios where the model can be represented as a tree.
Type โ
โBehavioral: Describes how objects interact/communicate between themselves.
โCreational: Describes how to instantiate an object without large and complex.
โ๏ธStructural: Describes how objects/classes are composed to form larger structures.
UML ๐
Participants ๐
โข Component:
- Declares the interface for objects in the composition with the default behaviour common to all classes
โข Leaf:
- Implements Component interface
- Represents leaf objects (components with no children)
โข Composite:
- Implements Component interface
- Declares an interface for accessing and managing its child components
- Store children components
Sample Code ๐ฎ
Structural Example ๐๏ธ
public static class CompositeStructural
{
public static void Execute()
{
Composite lRoot = new Composite("Root");
lRoot.Add(new Leaf("Leaf A"));
lRoot.Add(new Leaf("Leaf B"));
Composite lComposite = new Composite("Composite X");
lComposite.Add(new Leaf("Leaf XA"));
lComposite.Add(new Leaf("Leaf XB"));
lRoot.Add(lComposite);
lRoot.Add(new Leaf("Leaf C"));
Leaf lLeaf = new Leaf("Leaf D");
lRoot.Add(lLeaf);
lRoot.Remove(lLeaf);
// Recursively display tree
lRoot.Display(1);
}
}
public abstract class Component
{
protected string _Name;
public Component(string prName)
{
_Name = prName;
}
public abstract void Display(int prDepth);
}
public class Composite : Component
{
private List<Component> _Children = new List<Component>();
public Composite(string prName)
: base(prName)
{
}
public void Add(Component prComponent)
{
_Children.Add(prComponent);
}
public void Remove(Component prComponent)
{
_Children.Remove(prComponent);
}
public override void Display(int prDepth)
{
Console.WriteLine(new String('-', prDepth) + _Name);
// Recursively display child nodes
foreach (Component lComponentCurrent in _Children)
{
lComponentCurrent.Display(prDepth + 2);
}
}
}
public class Leaf : Component
{
// Constructor
public Leaf(string prName)
: base(prName)
{
}
public override void Display(int prDepth)
{
Console.WriteLine(new String('-', prDepth) + _Name);
}
}
Output
Real-world Example ๐ฅ
public static class CompositePractical
{
public static void Execute()
{
ManagementMember lDirector = new ManagementMember("Director");
ManagementMember lManagerDeptA = new ManagementMember("Manager Department A");
lManagerDeptA.Add(new StaffMember("Staff 1 Department A"));
lManagerDeptA.Add(new StaffMember("Staff 2 Department A"));
ManagementMember lSupervisorDeptA = new ManagementMember("Supervisor Department A");
lSupervisorDeptA.Add(new StaffMember("Staff 3 Department A"));
lSupervisorDeptA.Add(new StaffMember("Staff 4 Department A"));
lManagerDeptA.Add(lSupervisorDeptA);
ManagementMember lManagerDeptB = new ManagementMember("Manager Department B");
lManagerDeptB.Add(new StaffMember("Staff 1 Department B"));
lManagerDeptB.Add(new StaffMember("Staff 2 Department B"));
lManagerDeptB.Add(new StaffMember("Staff 3 Department B"));
lManagerDeptB.Add(new StaffMember("Staff 4 Department B"));
lDirector.Add(lManagerDeptA);
lDirector.Add(lManagerDeptB);
lDirector.Display(1);
}
}
public abstract class Employee
{
protected string _Name;
public Employee(string prName)
{
_Name = prName;
}
public abstract void Display(int prDepth);
}
public class ManagementMember : Employee
{
private List<Employee> _Employees = new List<Employee>();
public ManagementMember(string prName)
: base(prName)
{
}
public void Add(Employee prEmployee)
{
_Employees.Add(prEmployee);
}
public void Remove(Employee prEmployee)
{
_Employees.Remove(prEmployee);
}
public override void Display(int prDepth)
{
Console.WriteLine(new String('-', prDepth) + _Name);
// Recursively display child nodes
foreach (Employee lEmployeeCurrent in _Employees)
{
lEmployeeCurrent.Display(prDepth + 2);
}
}
}
public class StaffMember : Employee
{
// Constructor
public StaffMember(string prName)
: base(prName)
{
}
public override void Display(int prDepth)
{
Console.WriteLine(new String('-', prDepth) + _Name);
}
}
Output
Source Code ๐ฒ
ย