The composite design pattern allows us to set up a tree structure and ask each element in the tree structure to perform a task. A typical tree structure would be a company organization chart, where the CEO is at the top and other employees at the bottom. After the tree structure is established, we can then ask each element, or employee, to perform a common operation.
The composite pattern classifies each element in the tree as a composite or a leaf. A composite means that there can be other elements below it, whereas a leaf cannot have any elements below it. Therefore the leaf must be at the very bottom of the tree. The concept is shown in the diagram below,
UML Class Diagram
Here, we can see the difference between a composite element and the leaf.
In a Project we have Tech Lead and Developers. The Tech Lead can manage other Tech Leads or Developers under him\her.
The Tech Lead will be the composites.
The developers do not manage anyone and they will be the leafs.
All the TechLeads and developers are employees, and as an employee you can always do some work. (this is the common operation of the elements).
Below are the implementation details and the output for our example. Notice that, we can add any number of developers at any level of the organization and the composite will show the type of work for everyone under the composite.
Implementation
Create IComponent interface i.e., IEmployee
Create leaf class i.e., Developer
Create composite class.i.e., TechLead
Create a client to test above implemented composite pattern,
Output
Nick will make sure to get work done from his team members.
lead devloper creates design of application.
Zonan implements automated tests..
John Slater develops applications..
Summary
The composite pattern classifies each element in the tree as a composite or a leaf. A composite means that there can be other elements below it, whereas a leaf cannot have any elements below it. Therefore the leaf must be at the very bottom of the tree. The concept is shown in the diagram below,
UML Class Diagram
Here, we can see the difference between a composite element and the leaf.
- The IComponent interface defines the methods that both the Composite class and the Leaf class must implement. The Operation method is the common method that all elements in the tree structure can perform. The IComponent simply represents an element in the tree.
- The Leaf classes are elements that cannot have any elements below it, and it only has Operation method to perform the task for the element.
- The Composite classes are elements that can have 0 or more elements below it. The methods that it supports are as follows:
- The AddComponent method adds an element below it
- The GetChild method gets all the elements below it
- The Operation method performs the task for the element itself
- The RemoveComponent method deletes an element below it
In a Project we have Tech Lead and Developers. The Tech Lead can manage other Tech Leads or Developers under him\her.
The Tech Lead will be the composites.
The developers do not manage anyone and they will be the leafs.
All the TechLeads and developers are employees, and as an employee you can always do some work. (this is the common operation of the elements).
Below are the implementation details and the output for our example. Notice that, we can add any number of developers at any level of the organization and the composite will show the type of work for everyone under the composite.
Implementation
Create IComponent interface i.e., IEmployee
public interface IEmployee
{
void DoSomeWork();
}
Create leaf class i.e., Developer
public class Developer : IEmployee
{
private string _name;
private string _typeOfWork;
public Developer(string name, string typeOfWork)
{
_name = name;
_typeOfWork = typeOfWork;
}
void IEmployee.DoSomeWork()
{
Console.WriteLine("{0} {1}.", _name, _typeOfWork);
}
}
Create composite class.i.e., TechLead
public class TechLead : IEmployee
{
private string _name;
private string _typeOfWork;
private List_reportees = new List ();
public TechLead(string name, string typeOfWork)
{
_name = name;
_typeOfWork = typeOfWork;
}
public void AddSubordinate(IEmployee employee)
{
_reportees.Add(employee);
}
void IEmployee.DoSomeWork()
{
Console.WriteLine("{0} {1}", _name, _typeOfWork);
// show all the reportees work
foreach (IEmployee i in _reportees)
i.DoSomeWork();
}
}
Create a client to test above implemented composite pattern,
private void btnComposite_Click(object sender, EventArgs e)
{
TechLead lead1 = new TechLead("Nick", "will make sure to get work done from his team members.");
TechLead lead2 = new TechLead("lead devloper", "creates design of application.");
Developer dev1 = new Developer("John Slater", "develops applications.");
Developer dev2 = new Developer("Zonan", "implements automated tests.");
// Create team
lead1.AddSubordinate(lead2);
lead1.AddSubordinate(dev1);
lead2.AddSubordinate(dev2);
// Nick tells what he do and asks everyone else what they does
if (lead1 is DesignPatterns.Composite.IEmployee)
(lead1 as DesignPatterns.Composite.IEmployee).DoSomeWork();
}
Output
Nick will make sure to get work done from his team members.
lead devloper creates design of application.
Zonan implements automated tests..
John Slater develops applications..
Summary
- The group of objects should be treated similarly as a single object.
- Manipulating a single object should be as similar to manipulating a group of objects.
- Recursive formation and tree structure for composite should be noted.
- Clients access the whole hierarchy through the components and they are not aware about whether they are dealing with leaf or composites.