Tuesday, August 18, 2009

Composite Design Pattern in C#

Intent:

The Composite composes objects into tree structures, and lets clients treat individual objects and compositions uniformly. The Composite pattern is useful when individual objects as well as aggregates of those objects are to be treated uniformly.

Non-Software Example:

An everyday example is enumerating the contents of a file folder. A folder may contain not only files, but subfolders as well. An application designed to recursively display the list of all files in some top-level folder can use a conditional statement to distinguish between files and directories, and traverse down the directory tree to display the names of files in the subfolders. The composite pattern is a design pattern that is used when creating hierarchical object models.

Benefits:

A better approach for the above issue can be answered by the Composite pattern. In this approach, every folder item, be it a file, a subfolder, a network printer for any directory element, is an instance of a class that conforms to an interface offering a method to display a user-friendly name of the element. In this case, the client application does not have to treat each element differently, thereby reducing the complexity of the application logic. Also incase there is a new type also added to the folder the composite pattern will automatically handle it. Let’s say tomorrow we have a new file type in the folder say “network connection” type. If the “network connection” implements the same interface as the files and folders we do not need to change any code.

UML:



The UML above describes the implementation details of composite pattern. Let us understand each of these block separately

Component: The component is an abstract class which acts as a base class for all the objects in the hierarchy. We can also use an interface to define this.

Composite: The composite block is most important in the composite pattern. This class contains methods to add and remove the child components and methods retrieve those children objects through a collection. Each of these objects can also be a composite containing its own children. The composite implements IEnumerable interface. This idea behind this implementation is that it helps in looping through the objects.

Leaf: These classes used to define tree with in the tree and cannot have their children.

Software Example & Explanation of Code:

Let us discuss the software example for the composite pattern. The most common place where you can find the hierarchy is a work place. Let us create fictitious organization where John is the CEO. Sam and Tina are the Vice president of the organization and both of then report to John. Rob and Andy are contract employees and they in turn report to Sam. Lucy is a normal employee reporting to Sam. Maria, Bill and Scott are general employees reporting to Tina.



Let us build the composite pattern one by one. First the interface which is the “component” block in the above UML

IEmployee.cs

namespace CompositePattern
{
public interface IEmployee
{
string Name{get;set;}
}
}
Next is the Employee class implementing the IEmployee and the interface IEnumerable

Employee.cs

namespace CompositePattern
{
public class Employee:IEmployee,IEnumerable
{
private List subordinates = new List();
private string _Name;

//Implemention of IEmployee
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
//Private method implementation
public void AddSubOrdinate(IEmployee reportee)
{
subordinates.Add(reportee);
}

public void GetSubOrdinate(IEmployee reportee)
{
subordinates.Remove(reportee);
}

public IEmployee GetSubOrdinateDetails(int intEmp)
{
return subordinates[intEmp];
}

//Implemention of IEnumerable
public IEnumerator GetEnumerator()
{
foreach (IEmployee empobj in subordinates)
{
yield return empobj;
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

}
}
Since we have Rob and Andy as contract employees let us create a contract class for them implementing the same IEmployee interface. Below is the code for the contract class

Contract.cs
namespace CompositePattern
{
public class Contract:IEmployee
{
private string _Name;

public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}

}
}
Finally the client which will demonstrate the composite pattern. Create an aspx page and add the following code.

Default.aspx.cs

namespace CompositePattern
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Add CEO Details
Employee john = new Employee();
john.Name = "CEO--John";

//ADD VP Details
Employee Sam = new Employee();
Sam.Name = "VP--Sam";
john.AddSubOrdinate(Sam);

Employee Tina = new Employee();
Tina.Name = "VP--Tina";
john.AddSubOrdinate(Tina);

//Add subordinate Details for Sam
Contract Rob = new Contract();
Rob.Name = "Employee --Rob";
Sam.AddSubOrdinate(Rob);

Contract Andy = new Contract();
Andy.Name = "Employee --Andy";
Sam.AddSubOrdinate(Andy);

Employee Lucy = new Employee();
Lucy.Name = "Employee --Lucy";
Sam.AddSubOrdinate(Lucy);

//Add subordinate Details for Tina
Employee Maria = new Employee();
Maria.Name = "Employee --Maria";
Tina.AddSubOrdinate(Maria);

Employee Bill = new Employee();
Bill.Name = "Employee --Bill";
Tina.AddSubOrdinate(Bill);

Employee Scott = new Employee();
Scott.Name = "Employee Scott";
Tina.AddSubOrdinate(Scott);

//Here is the real implementation

Response.Write(john.Name + "
");
foreach (Employee vp in john)
{
Response.Write(vp.Name+"
");
foreach (IEmployee emp in vp)
{
Response.Write(emp.Name + "
");
}
}
}
}
}
Here is the output
CEO--John
VP--Sam
Employee --Rob
Employee --Andy
Employee --Lucy
VP--Tina
Employee --Maria
Employee --Bill
Employee Scott

The code is self explanatory. The entire source code is available @ http://www.csharppatterns.com/.

Reference http://msdn.microsoft.com/en-us/magazine/cc301852.aspx

No comments: