Saturday, October 08, 2011

Difference between composition and aggregation in terms of C#

Both composition and aggregations are types of associations.

An association is represented by an arrow:

An aggregation is represented by an hollow diamond:

And composition is represented by a filled in diamond:

Lets look at it in terms of a diagram: (taken from Kenny Lee’s blog)

image

Department is a composition, because its lifetime is dictated by the lifetime of the company object. (if a company ceases to exist, then the department ceases to exist). But on the other hand an employee is an aggregation, as a department if made up of employees, but if the department is shut down, the employees do not cease to exist. (they could get reassigned to other departments).

Here is what the code would look like in C#

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Department : IEnumerable
{
    //employees is an agreggation of employees
    private List<Employee> _employees = new List<Employee>();

    public string Name { get; set; }

    public void Add(Employee employee)
    {
        _employees.Add(employee);
    }

    public void Remove(Employee employee)
    {
        _employees.Remove(employee);
    }

    public Employee this[int index]
    {
        get { return _employees[index]; }
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        foreach (Employee employee in _employees)
        {
            yield return employee;
        }
    }
}

public class Company : IEnumerable, IDisposable //implementing IDisposable just to show departments lifetime is the same as Company's lifetime
{
    //departments is a composition.
    //departments lifetime controlled by lifetime of Company
    private Dictionary<string, Department> _departments = new Dictionary<string, Department>();

public Company(string[] departmentsToCreate)
    {
        Console.WriteLine("Creating the company and its departments");
        foreach(string departmentToCreate in departmentsToCreate)
        {
            _departments.Add(departmentToCreate, new Department{Name = departmentToCreate});
        }
    }

    public Department this[string departmentName]
    {
        get { return _departments[departmentName]; }
    }

    public void ReassignAndCloseDepartmentEmployees(string departmentToCloseName, string reassignmentDepartmentName)
    {
        Department fromDepartment = this[departmentToCloseName];
        Department toDepartment = this[reassignmentDepartmentName];
        foreach (Employee employee in fromDepartment)
        {
            toDepartment.Add(employee);
        }
        _departments.Remove(departmentToCloseName);
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        foreach (KeyValuePair<string, Department> departmentKvp in _departments)
        {
            yield return departmentKvp.Value;
        }
    }

void IDisposable.Dispose()
    {
        Console.WriteLine("Company is being disposed, dispose departments too");
        _departments.Clear(); //company is dead, departments are being killed, but employees live on
        _departments = null;
    }

}

public class Test
{

    void Main()
    {
        using (Company company = new Company(new string[] { "EIS", "Sales" }))
        {
            company["EIS"].Add(new Employee { FirstName = "Raj", LastName = "Rao" });
            company["EIS"].Add(new Employee { FirstName = "Arnold", LastName = "Schwarzneger" });

            company["Sales"].Add(new Employee { FirstName = "Steve", LastName = "Jobs" });
            company["Sales"].Add(new Employee { FirstName = "Bill", LastName = "Gates" });

            company.ReassignAndCloseDepartmentEmployees("Sales", "EIS");
        }

    }
}

And here is what the output looks like (in LinqPad)

image

The class diagram from Visual Studio

image

No comments: