Saturday, 12 October 2013

Composite Design Pattern - Implementation

Master Practical Java Architecture & Design Patterns!

Subscribe to Ram N Java for clean coding tutorials, GoF design patterns, and real-world system implementations!

🔔 Subscribe to Ram N Java

The Challenge of Tree Structures & Hierarchies

In software development, systems frequently model part-whole hierarchies such as file system directories, organizational management trees, or complex graphical UI components.

Without a clean architectural approach, client code is forced to distinguish between leaf nodes (individual items) and branches (composite groups containing child items). This requires repetitive type-checking conditionals (instanceof checks) and separate logic paths throughout your application, making the codebase rigid and brittle.

Hands-On Implementation Architecture

The Composite Design Pattern solves this challenge by letting clients treat individual objects and compositions of objects uniformly:

  • Component: An abstract class or interface declaring common operations (e.g., showDetails()) for both simple and complex objects in the hierarchy.
  • Leaf: Represents individual building blocks with no child nodes. A Leaf implements the Component interface directly to perform specific work.
  • Composite: Represents branch nodes that hold a collection of child Components. It implements child management methods (add(), remove()) and delegates operations recursively to its children.
  • Client: Interacts with all elements strictly through the common Component interface, completely oblivious to whether it is operating on a single leaf or an entire subtree.

Key Architectural Benefits

Implementing the Composite pattern brings substantial design advantages:

  • Uniform Client Code: Clients treat individual primitives and complex object trees identically without writing type-checking logic.
  • Open/Closed Principle: Introducing new leaf or composite component types requires no changes to existing classes or client code.
  • Recursive Simplicity: Operations propagate down tree structures effortlessly via clean recursive calls.

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=HM1Zn-uVF60

Click the below Image to Enlarge

Composite Design Pattern - Implementation

Composite Design Pattern - Implementation - Class Diagram

























IEmployee.java

public interface IEmployee
{
public int getYearlySalary();

}

Employee.java

import java.util.ArrayList;

// Employee class is the Composite node [i.e. it can have other objects below it]

public class Employee implements IEmployee
{

private String               name;
private int                  monthlySalary;
// Employee designation Can be CEO,Dev Manager,QA Manager,Dev TeamLead,QA TeamLead
private String               designation;

private ArrayList<IEmployee> subordinateList = new ArrayList<IEmployee>();

public Employee( String name, int monthlySalary, String designation )
{
super();
this.name = name;
this.monthlySalary = monthlySalary;
this.designation = designation;
}

public String getName()
{
return name;
}

public void setName( String name )
{
this.name = name;
}

public int getMonthlySalary()
{
return monthlySalary;
}

public void setMonthlySalary( int monthlySalary )
{
this.monthlySalary = monthlySalary;
}

public String getDesignation()
{
return designation;
}

public void setDesignation( String designation )
{
this.designation = designation;
}

public ArrayList<IEmployee> getSubordinateList()
{
return subordinateList;
}

public void setSubordinateList( ArrayList<IEmployee> subordinateList )
{
this.subordinateList = subordinateList;
}

@Override
public int getYearlySalary()
{
return monthlySalary * 12;
}

public void addSubordinate( IEmployee employee )
{
subordinateList.add(employee);
}

public void removeSubordinate( IEmployee employee )
{
subordinateList.remove(employee);
}

public ArrayList<IEmployee> getChilds()
{
return getSubordinateList();
}

}


SoftwareEngineer.java

// SoftwareEngineer class is the Leaf node [i.e. it cann't have other objects below it]

public class SoftwareEngineer implements IEmployee
{
private String name;
private int    monthlySalary;
// Employee designation Can be Dev Software Engineer, QA Software Engineer
private String designation;

public SoftwareEngineer( String name, int monthlySalary, String designation )
{
super();
this.name = name;
this.monthlySalary = monthlySalary;
this.designation = designation;
}

public String getName()
{
return name;
}

public void setName( String name )
{
this.name = name;
}

public int getMonthlySalary()
{
return monthlySalary;
}

public void setMonthlySalary( int monthlySalary )
{
this.monthlySalary = monthlySalary;
}

public String getDesignation()
{
return designation;
}

public void setDesignation( String designation )
{
this.designation = designation;
}

@Override
public int getYearlySalary()
{
return monthlySalary * 12;
}

}


CompositePatternDemo.java

import java.util.ArrayList;

public class CompositePatternDemo
{

public static void main( String[] args )
{
Employee dave = new Employee("Dave", 200000, "CEO");

Employee peter = new Employee("peter", 100000, "Dev Manager");
Employee john = new Employee("John", 100000, "QA Manager");

Employee rohan = new Employee("Rohan", 50000, "Dev TeamLead");
Employee vijay = new Employee("Vijay", 50000, "QA TeamLead");

SoftwareEngineer raj = new SoftwareEngineer("Raj", 30000, "Dev Software Engineer");
SoftwareEngineer mohan = new SoftwareEngineer("Mohan", 30000, "Dev Software Engineer");
SoftwareEngineer hema = new SoftwareEngineer("Hema", 30000, "Dev Software Engineer");

SoftwareEngineer saran = new SoftwareEngineer("Saran", 20000, "QA Software Engineer");
SoftwareEngineer riya = new SoftwareEngineer("Riya", 20000, "QA Software Engineer");

dave.addSubordinate(peter);
dave.addSubordinate(john);

peter.addSubordinate(rohan);
john.addSubordinate(vijay);

rohan.addSubordinate(raj);
rohan.addSubordinate(mohan);
rohan.addSubordinate(hema);

vijay.addSubordinate(saran);
vijay.addSubordinate(riya);


getSubOrdinates(dave);
getSubOrdinates(peter);
getSubOrdinates(john);
getSubOrdinates(rohan);
getSubOrdinates(vijay);
getSubOrdinates(raj);
getSubOrdinates(mohan);
getSubOrdinates(hema);
getSubOrdinates(saran);
getSubOrdinates(riya);
}

private static void getSubOrdinates( IEmployee iemployee )
{
if( iemployee instanceof Employee )
{
Employee employee = (Employee) iemployee;
System.out.println("\n------------- SubordinatesListOf "+ employee.getName() +" : "+employee.getDesignation() + " ---------------------------------\n");
ArrayList<IEmployee> subordinatesListOfDave = employee.getChilds();
for( IEmployee iEmployee : subordinatesListOfDave )
{
if( iEmployee instanceof Employee )
{
Employee employeeObj = (Employee) iEmployee;
System.out.println(employeeObj.getName() + " : " + employeeObj.getDesignation() + ":"
               + employeeObj.getMonthlySalary() + ":" + employeeObj.getYearlySalary());
}
else
{
SoftwareEngineer softwareEngineer = (SoftwareEngineer) iEmployee;
System.out.println(softwareEngineer.getName() + " : "
               + softwareEngineer.getDesignation() + ":"
               + softwareEngineer.getMonthlySalary() + ":"
               + softwareEngineer.getYearlySalary());

}

}
}
else
{
System.out.println("\n--------------------------------------------------------------------------------------");
SoftwareEngineer softwareEngineer = (SoftwareEngineer) iemployee;
System.out.println("\nNo Subordinates for "+softwareEngineer.getName()+" : "+softwareEngineer.getDesignation()
+" : "+softwareEngineer.getMonthlySalary()+" : "+softwareEngineer.getYearlySalary());
}
}

}


Output

------------- SubordinatesListOf Dave : CEO ---------------------------------

peter : Dev Manager:100000:1200000
John : QA Manager:100000:1200000

------------- SubordinatesListOf peter : Dev Manager ---------------------------------

Rohan : Dev TeamLead:50000:600000

------------- SubordinatesListOf John : QA Manager ---------------------------------

Vijay : QA TeamLead:50000:600000

------------- SubordinatesListOf Rohan : Dev TeamLead ---------------------------------

Raj : Dev Software Engineer:30000:360000
Mohan : Dev Software Engineer:30000:360000
Hema : Dev Software Engineer:30000:360000

------------- SubordinatesListOf Vijay : QA TeamLead ---------------------------------

Saran : QA Software Engineer:20000:240000
Riya : QA Software Engineer:20000:240000

--------------------------------------------------------------------------------------

No Subordinates for Raj : Dev Software Engineer : 30000 : 360000

--------------------------------------------------------------------------------------

No Subordinates for Mohan : Dev Software Engineer : 30000 : 360000

--------------------------------------------------------------------------------------

No Subordinates for Hema : Dev Software Engineer : 30000 : 360000

--------------------------------------------------------------------------------------

No Subordinates for Saran : QA Software Engineer : 20000 : 240000

--------------------------------------------------------------------------------------

No Subordinates for Riya : QA Software Engineer : 20000 : 240000

No comments:

Post a Comment

Tutorials